Java tutorial
/** * Copyright 2012 NetDigital Sweden AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.nginious.http.plugin; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.concurrent.ConcurrentHashMap; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.WorkspaceJob; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jface.text.Document; class ServerManager implements IResourceChangeListener { private static ServerManager manager = null; private static Object lock = new Object(); private HashSet<String> startedServers; private HashSet<String> startingServers; private ConcurrentHashMap<String, HttpServerEnvironment> servers; private Logger logger; private ServerManager() { super(); this.servers = new ConcurrentHashMap<String, HttpServerEnvironment>(); this.startedServers = new HashSet<String>(); this.startingServers = new HashSet<String>(); int eventMask = IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_CLOSE | IResourceChangeEvent.PRE_DELETE | IResourceChangeEvent.PRE_BUILD | IResourceChangeEvent.POST_BUILD; ResourcesPlugin.getWorkspace().addResourceChangeListener(this, eventMask); this.logger = new Logger("/tmp/nginious.out"); } static ServerManager getInstance() { synchronized (lock) { if (manager == null) { manager = new ServerManager(); } return manager; } } Logger getLogger() { return this.logger; } public void resourceChanged(IResourceChangeEvent event) { logger.log("ENTER ServerManager.resourceChanged event={0}", event); int type = event.getType(); switch (type) { case IResourceChangeEvent.PRE_BUILD: logger.log("PRE_BUILD " + event); break; case IResourceChangeEvent.POST_BUILD: logger.log("POST_BUILD " + event); break; case IResourceChangeEvent.PRE_CLOSE: case IResourceChangeEvent.PRE_DELETE: IProject project = (IProject) event.getResource(); stopServer(project); logger.log("PRE_CLOSE | PRE_DELETE " + project.getName()); break; case IResourceChangeEvent.POST_CHANGE: IResourceDelta delta = event.getDelta(); IResourceDelta[] children = delta.getAffectedChildren(); logger.log("POST_CHANGE"); if (children != null && children.length > 0) { for (IResourceDelta child : children) { IResource resource = child.getResource(); if (resource instanceof IProject) { IProject changeProject = (IProject) resource; if (projectHasChanged(changeProject)) { logger.log("POST_CHANGE before " + changeProject.getName()); stopServer(changeProject); startServer(changeProject); logger.log("POST_CHANGE after " + changeProject.getName()); } } } } break; } logger.log("EXIT ServerManager.resourceChanged"); } private boolean projectHasChanged(IProject project) { logger.log("ENTER ServerManager.projectHasChanged project={0}", project); HttpServerEnvironment env = servers.get(project.getName()); if (env != null) { boolean changed = env.hasChanged(); logger.log("EXIT ServerManager.projectHasChanged changed={0}", changed); return changed; } // Verify that project has been fully created IFolder folder = project.getFolder("WebContent"); if (!folder.exists()) { logger.log("EXIT ServerManager.projectHasChanged changed=false"); return false; } boolean open = project.isOpen(); logger.log("EXIT ServerManager.projectHasChanged open={0}", open); return open; } void stopAllServers() { logger.log("ENTER ServerManager.stopAllServers"); for (HttpServerEnvironment env : servers.values()) { HttpServerProcess serverProcess = env.getServerProcess(); serverProcess.stop(); } servers.clear(); logger.log("EXIT ServerManager.stopAllServers"); } void stopServer(IProject project) { logger.log("ENTER ServerManager.stopServer project={0}", project); HttpServerEnvironment env = servers.remove(project.getName()); if (env != null) { HttpServerProcess serverProcess = env.getServerProcess(); serverProcess.stop(); } logger.log("EXIT SeverManager.stopServer"); } void restartServer(IProject project) { logger.log("ENTER ServerManager.restartServer project={0}", project); stopServer(project); startServer(project); logger.log("EXIT ServerManager.restartServer"); } void updateProjectWithPluginVersionDelayed(final IProject project) { WorkspaceJob job = new WorkspaceJob("Update Nginious plugin") { public IStatus runInWorkspace(IProgressMonitor monitor) { updateProjectWithPluginVersion(project); return Status.OK_STATUS; } }; job.schedule(); } private boolean updateProjectWithPluginVersion(IProject project) { logger.log("ENTER ServerManager.updateProjectWithPluginVersion project={0}", project); try { URL apiJar = NginiousPlugin.getApiJar(); String filePath = apiJar.toString(); filePath = filePath.substring(5); Path apiJarPath = new Path(filePath); IJavaProject javaProject = JavaCore.create(project); IClasspathEntry[] entries = javaProject.getRawClasspath(); ArrayList<IClasspathEntry> newEntries = new ArrayList<IClasspathEntry>(); boolean changed = false; for (IClasspathEntry entry : entries) { if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { IPath path = entry.getPath(); if (path.lastSegment() != null && path.lastSegment().endsWith("nginious-api.jar")) { changed = true; entry = JavaCore.newLibraryEntry(apiJarPath, null, null); } } newEntries.add(entry); } if (changed) { IProgressMonitor progress = new NullProgressMonitor(); entries = newEntries.toArray(new IClasspathEntry[newEntries.size()]); javaProject.setRawClasspath(entries, progress); javaProject.save(progress, true); } logger.log("EXIT ServerManager.updateProjectWithPluginVersion changed={0}", changed); return changed; } catch (JavaModelException e) { logger.log("ServerManager.updateProkectWithPluginVersion exception", e); return false; } catch (IOException e) { logger.log("ServerManager.updateProkectWithPluginVersion exception", e); return false; } } void startServer(IProject project) { logger.log("ENTER ServerManager.startServer project={0}", project); boolean done = false; try { if (servers.containsKey(project.getName())) { logger.log("EXIT ServerManager.startServer alreadyStarted"); return; } synchronized (this) { if (startingServers.contains(project.getName())) { logger.log("EXIT ServerManager.startServer alreadyStarting"); return; } startingServers.add(project.getName()); } synchronized (this.startedServers) { if (!startedServers.contains(project.getName())) { updateProjectWithPluginVersionDelayed(project); } } int listenPort = NginiousPlugin.DEFAULT_LISTEN_PORT; int minMemory = NginiousPlugin.DEFAULT_MIN_MEMORY; int maxMemory = NginiousPlugin.DEFAULT_MAX_MEMORY; String publishUrl = NginiousPlugin.DEFAULT_PUBLISH_URL; String publishUsername = NginiousPlugin.DEFAULT_PUBLISH_USERNAME; String publishPassword = NginiousPlugin.DEFAULT_PUBLISH_PASSWORD; String listenPortStr = project.getPersistentProperty(NginiousPlugin.LISTEN_PORT_PROP_KEY); if (listenPortStr != null) { listenPort = Integer.parseInt(listenPortStr); } publishUrl = project.getPersistentProperty(NginiousPlugin.PUBLISH_URL_PROP_KEY); publishUsername = project.getPersistentProperty(NginiousPlugin.PUBLISH_USERNAME_PROP_KEY); publishPassword = project.getPersistentProperty(NginiousPlugin.PUBLISH_PASSWORD_PROP_KEY); String minMemoryStr = project.getPersistentProperty(NginiousPlugin.MIN_MEMORY_PROP_KEY); if (minMemoryStr != null) { minMemory = Integer.parseInt(minMemoryStr); } String maxMemoryStr = project.getPersistentProperty(NginiousPlugin.MAX_MEMORY_PROP_KEY); if (maxMemoryStr != null) { maxMemory = Integer.parseInt(maxMemoryStr); } IPath projectPath = project.getLocation(); IPath webappsPath = projectPath.append("WebContent"); HttpServerProcess serverProcess = new HttpServerProcess(project.getName(), listenPort, publishPassword, minMemory, maxMemory, webappsPath.toFile(), this.logger); serverProcess.start(); LogViewConsumer accessLogConsumer = new LogViewConsumer(this.logger, serverProcess.getAccessLogPath()); LogViewConsumer messageLogConsumer = new LogViewConsumer(this.logger, serverProcess.getServerLogPath()); HttpServerEnvironment env = new HttpServerEnvironment(project, serverProcess, accessLogConsumer, messageLogConsumer); env.setPort(listenPort); env.setPublishUrl(publishUrl); env.setPublishUsername(publishUsername); env.setPublishPassword(publishPassword); servers.put(project.getName(), env); synchronized (this.startedServers) { startedServers.add(project.getName()); } done = true; logger.log("EXIT ServerManager.startServer"); } catch (IOException e) { String title = Messages.ServerManager_server_error_title; String message = Messages.ServerManager_server_error_message + " " + project.getName(); MessagesUtils.displayMessageDialog(e.getMessage(), null, title, message); logger.log("ServerManager.startServer exception", e); } catch (NumberFormatException e) { String title = Messages.ServerManager_listen_port_error_title; String message = Messages.ServerManager_listen_port_error_message + " " + project.getName(); MessagesUtils.displayMessageDialog(e.getMessage(), null, title, message); logger.log("ServerManager.startServer exception", e); } catch (CoreException e) { String title = Messages.ServerManager_properties_error_title; String message = Messages.ServerManager_listen_port_error_message + " " + project.getName(); MessagesUtils.perform(e, null, title, message); logger.log("ServerManager.startServer exception", e); } catch (Throwable t) { logger.log("ServerManager.startServer exception", t); } finally { synchronized (this) { startingServers.remove(project.getName()); } if (!done) { synchronized (this.startedServers) { startedServers.remove(project.getName()); } servers.remove(project.getName()); } } } IProject checkListenPortUsage(int listenPort) { logger.log("ENTER ServerManager.checkListenPortUsage listenPort={0}", listenPort); Collection<HttpServerEnvironment> envs = servers.values(); for (HttpServerEnvironment env : envs) { if (env.getPort() == listenPort) { IProject project = env.getProject(); logger.log("EXIT ServerMamager.checkListenPortUsage project={0}", project); } } logger.log("EXIT ServerManager.checkListenPortUsage project=null"); return null; } Document getMessageLogDocument(IProject project) { logger.log("ENTER ServerManager.getMessageLogDocument project=", project); HttpServerEnvironment env = servers.get(project.getName()); if (env != null) { LogViewConsumer consumer = env.getMessageLogConsumer(); if (consumer != null) { Document doc = consumer.getDocument(); logger.log("EXIT ServerManager.getMessageLogDocument document={0}", doc); return doc; } } logger.log("EXIT ServerManager.getMessageLogDocument document=null"); return null; } Document getAccessLogDocument(IProject project) { logger.log("ENTER ServerManager.getAccessLogDocument project={0}", project); HttpServerEnvironment env = servers.get(project.getName()); if (env != null) { LogViewConsumer consumer = env.getAccessLogConsumer(); if (consumer != null) { Document doc = consumer.getDocument(); logger.log("EXIT ServerManager.getAccessLogDocument document={0}", doc); return doc; } } logger.log("EXIT ServerManager.getAccessLogDocument document=null"); return null; } private class HttpServerEnvironment { private IProject project; private int port; @SuppressWarnings("unused") private String publishUrl; @SuppressWarnings("unused") private String publishUsername; private String publishPassword; private HttpServerProcess serverProcess; private LogViewConsumer accessLogConsumer; private LogViewConsumer messageLogConsumer; private HttpServerEnvironment(IProject project, HttpServerProcess serverProcess, LogViewConsumer accessLogConsumer, LogViewConsumer messageLogConsumer) { super(); this.project = project; this.serverProcess = serverProcess; this.accessLogConsumer = accessLogConsumer; this.messageLogConsumer = messageLogConsumer; } private IProject getProject() { return this.project; } private void setPort(int port) { this.port = port; } private int getPort() { return this.port; } private void setPublishUrl(String publishUrl) { this.publishUrl = publishUrl; } private void setPublishUsername(String publishUsername) { this.publishUsername = publishUsername; } private void setPublishPassword(String publishPassword) { this.publishPassword = publishPassword; } private HttpServerProcess getServerProcess() { return this.serverProcess; } private LogViewConsumer getMessageLogConsumer() { return this.messageLogConsumer; } private LogViewConsumer getAccessLogConsumer() { return this.accessLogConsumer; } private boolean hasChanged() { try { String newPort = project.getPersistentProperty(NginiousPlugin.LISTEN_PORT_PROP_KEY); String newPublishPassword = project.getPersistentProperty(NginiousPlugin.PUBLISH_PASSWORD_PROP_KEY); if (!Integer.toString(this.port).equals(newPort)) { return true; } if (!publishPassword.equals(newPublishPassword)) { return true; } return false; } catch (CoreException e) { return false; } } } }