You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2013/03/13 13:21:07 UTC

svn commit: r1455901 [1/2] - in /karaf/trunk: ./ instance/command/src/main/java/org/apache/karaf/instance/main/ instance/command/src/test/java/org/apache/karaf/instance/main/ instance/core/ instance/core/src/main/java/org/apache/karaf/instance/core/ in...

Author: gnodet
Date: Wed Mar 13 12:21:07 2013
New Revision: 1455901

URL: http://svn.apache.org/r1455901
Log:
[KARAF-2221] The admin service is not safe when used to create / start agents quickly

Added:
    karaf/trunk/util/src/main/java/org/apache/karaf/util/properties/
    karaf/trunk/util/src/main/java/org/apache/karaf/util/properties/FileLockUtils.java
Modified:
    karaf/trunk/instance/command/src/main/java/org/apache/karaf/instance/main/Execute.java
    karaf/trunk/instance/command/src/test/java/org/apache/karaf/instance/main/ExecuteTest.java
    karaf/trunk/instance/core/pom.xml
    karaf/trunk/instance/core/src/main/java/org/apache/karaf/instance/core/Instance.java
    karaf/trunk/instance/core/src/main/java/org/apache/karaf/instance/core/InstanceService.java
    karaf/trunk/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceImpl.java
    karaf/trunk/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
    karaf/trunk/instance/core/src/main/resources/OSGI-INF/blueprint/instance-core.xml
    karaf/trunk/main/pom.xml
    karaf/trunk/main/src/main/java/org/apache/karaf/main/InstanceHelper.java
    karaf/trunk/pom.xml
    karaf/trunk/util/pom.xml

Modified: karaf/trunk/instance/command/src/main/java/org/apache/karaf/instance/main/Execute.java
URL: http://svn.apache.org/viewvc/karaf/trunk/instance/command/src/main/java/org/apache/karaf/instance/main/Execute.java?rev=1455901&r1=1455900&r2=1455901&view=diff
==============================================================================
--- karaf/trunk/instance/command/src/main/java/org/apache/karaf/instance/main/Execute.java (original)
+++ karaf/trunk/instance/command/src/main/java/org/apache/karaf/instance/main/Execute.java Wed Mar 13 12:21:07 2013
@@ -130,7 +130,6 @@ public class Execute {
                 
         InstanceServiceImpl instanceService = new InstanceServiceImpl();
         instanceService.setStorageLocation(storageFile);
-        instanceService.init();
         command.setInstanceService(instanceService);
         command.execute(null);
     }

Modified: karaf/trunk/instance/command/src/test/java/org/apache/karaf/instance/main/ExecuteTest.java
URL: http://svn.apache.org/viewvc/karaf/trunk/instance/command/src/test/java/org/apache/karaf/instance/main/ExecuteTest.java?rev=1455901&r1=1455900&r2=1455901&view=diff
==============================================================================
--- karaf/trunk/instance/command/src/test/java/org/apache/karaf/instance/main/ExecuteTest.java (original)
+++ karaf/trunk/instance/command/src/test/java/org/apache/karaf/instance/main/ExecuteTest.java Wed Mar 13 12:21:07 2013
@@ -117,56 +117,6 @@ public class ExecuteTest extends TestCas
         }        
     }
     
-    public void testExecute() throws Exception {
-        final File tempFile = createTempDir(getName());
-        Properties p = new Properties();
-        p.setProperty("ssh.port", "1302");
-        p.setProperty("rmi.registry.port", "1122");
-        p.setProperty("rmi.server.port", "44444");
-        FileOutputStream fos = new FileOutputStream(new File(tempFile, InstanceServiceImpl.STORAGE_FILE));
-        p.store(fos, "");
-        fos.close();
-
-        final List<InstanceServiceImpl> instanceServices = new ArrayList<InstanceServiceImpl>();
-        try {
-            InstanceCommandSupport mockCommand = EasyMock.createStrictMock(InstanceCommandSupport.class);
-            mockCommand.setInstanceService((InstanceService) EasyMock.anyObject());
-            EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
-                public Object answer() throws Throwable {
-                    InstanceServiceImpl instanceService = (InstanceServiceImpl) EasyMock.getCurrentArguments()[0];
-                    assertEquals(tempFile, instanceService.getStorageLocation());
-                    instanceServices.add(instanceService);
-                    return null;
-                }
-            });
-            
-            EasyMock.expect(mockCommand.execute(null)).andAnswer(new IAnswer<Object>() {
-                public Object answer() throws Throwable {
-                    // The Instances Service should be initialized at this point.
-                    // One way to find this out is by reading out the port number
-                    InstanceServiceImpl instanceService = instanceServices.get(0);
-                    Field sshField = InstanceServiceImpl.class.getDeclaredField("defaultSshPortStart");
-                    sshField.setAccessible(true);
-                    assertEquals(1302, sshField.get(instanceService));
-                    Field rmiRegistryField = InstanceServiceImpl.class.getDeclaredField("defaultRmiRegistryPortStart");
-                    rmiRegistryField.setAccessible(true);
-                    assertEquals(1122, rmiRegistryField.get(instanceService));
-                    Field rmiServerField = InstanceServiceImpl.class.getDeclaredField("defaultRmiServerPortStart");
-                    rmiServerField.setAccessible(true);
-                    assertEquals(44444, rmiServerField.get(instanceService));
-                    return null;
-                }
-            });
-            EasyMock.replay(mockCommand);            
-            
-            Execute.execute(mockCommand, tempFile, new String [] {"test"});
-            
-            EasyMock.verify(mockCommand);
-        } finally {
-            delete(tempFile);
-        }
-    }
-
     private static File createTempDir(String name) throws IOException {
         final File tempFile = File.createTempFile(name, null);
         tempFile.delete();

Modified: karaf/trunk/instance/core/pom.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/instance/core/pom.xml?rev=1455901&r1=1455900&r2=1455901&view=diff
==============================================================================
--- karaf/trunk/instance/core/pom.xml (original)
+++ karaf/trunk/instance/core/pom.xml Wed Mar 13 12:21:07 2013
@@ -63,6 +63,11 @@
         </dependency>
 
         <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+        </dependency>
+
+        <dependency>
             <groupId>org.apache.servicemix.bundles</groupId>
             <artifactId>org.apache.servicemix.bundles.junit</artifactId>
             <scope>test</scope>
@@ -143,7 +148,8 @@
                             org.apache.karaf.jpm,
                             org.apache.karaf.jpm.impl,
                             org.apache.karaf.instance.core.internal,
-                            org.apache.felix.utils.properties;-split-package:=merge-first
+                            org.apache.felix.utils.properties;-split-package:=merge-first,
+                            org.apache.karaf.util.properties
                         </Private-Package>
                     </instructions>
                 </configuration>

Modified: karaf/trunk/instance/core/src/main/java/org/apache/karaf/instance/core/Instance.java
URL: http://svn.apache.org/viewvc/karaf/trunk/instance/core/src/main/java/org/apache/karaf/instance/core/Instance.java?rev=1455901&r1=1455900&r2=1455901&view=diff
==============================================================================
--- karaf/trunk/instance/core/src/main/java/org/apache/karaf/instance/core/Instance.java (original)
+++ karaf/trunk/instance/core/src/main/java/org/apache/karaf/instance/core/Instance.java Wed Mar 13 12:21:07 2013
@@ -25,12 +25,14 @@ public interface Instance {
 
     String getName();
 
+    @Deprecated
     void setName(String name);
     
     boolean isRoot();
 
     String getLocation();
 
+    @Deprecated
     void setLocation(String location);
 
     int getPid();
@@ -59,5 +61,6 @@ public interface Instance {
 
     String getState() throws Exception;
 
+    @Deprecated
     boolean isAttached();
 }

Modified: karaf/trunk/instance/core/src/main/java/org/apache/karaf/instance/core/InstanceService.java
URL: http://svn.apache.org/viewvc/karaf/trunk/instance/core/src/main/java/org/apache/karaf/instance/core/InstanceService.java?rev=1455901&r1=1455900&r2=1455901&view=diff
==============================================================================
--- karaf/trunk/instance/core/src/main/java/org/apache/karaf/instance/core/InstanceService.java (original)
+++ karaf/trunk/instance/core/src/main/java/org/apache/karaf/instance/core/InstanceService.java Wed Mar 13 12:21:07 2013
@@ -22,6 +22,7 @@ public interface InstanceService {
 
     void renameInstance(String name, String newName, boolean printOutput) throws Exception;
 
+    @Deprecated
     void refreshInstance() throws Exception;
 
     Instance cloneInstance(String name, String cloneName, InstanceSettings settings, boolean printOutput) throws Exception;

Modified: karaf/trunk/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceImpl.java
URL: http://svn.apache.org/viewvc/karaf/trunk/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceImpl.java?rev=1455901&r1=1455900&r2=1455901&view=diff
==============================================================================
--- karaf/trunk/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceImpl.java (original)
+++ karaf/trunk/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceImpl.java Wed Mar 13 12:21:07 2013
@@ -16,416 +16,95 @@
  */
 package org.apache.karaf.instance.core.internal;
 
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.net.Socket;
-import java.net.URL;
-import java.net.UnknownHostException;
-
-import org.apache.felix.utils.properties.Properties;
 import org.apache.karaf.instance.core.Instance;
-import org.apache.karaf.jpm.Process;
-import org.apache.karaf.jpm.ProcessBuilderFactory;
-import org.apache.karaf.jpm.impl.ProcessBuilderFactoryImpl;
-import org.apache.karaf.jpm.impl.ScriptUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 public class InstanceImpl implements Instance {
 
-    private static final Logger LOG = LoggerFactory.getLogger(InstanceImpl.class);
-
-    private static final String CONFIG_PROPERTIES_FILE_NAME = "config.properties";
-    private static final String KARAF_SHUTDOWN_PORT = "karaf.shutdown.port";
-    private static final String KARAF_SHUTDOWN_HOST = "karaf.shutdown.host";
-    private static final String KARAF_SHUTDOWN_PORT_FILE = "karaf.shutdown.port.file";
-    private static final String KARAF_SHUTDOWN_COMMAND = "karaf.shutdown.command";
-    private static final String DEFAULT_SHUTDOWN_COMMAND = "SHUTDOWN";
-
-    private InstanceServiceImpl service;
+    private final InstanceServiceImpl service;
     private String name;
-    private String location;
-    private String javaOpts;
-    private Process process;
-    private boolean root;
-
-    private final ProcessBuilderFactory processBuilderFactory;
-
-    public InstanceImpl(InstanceServiceImpl service, String name, String location, String javaOpts) {
-        this(service, name, location, javaOpts, false);
-        
-    }
-    
-    public InstanceImpl(InstanceServiceImpl service, String name, String location, String javaOpts, boolean root) {
+
+    public InstanceImpl(InstanceServiceImpl service, String name) {
         this.service = service;
         this.name = name;
-        this.location = location;
-        this.javaOpts = javaOpts;
-        this.root = root;
-        this.processBuilderFactory = new ProcessBuilderFactoryImpl();
-    }
-
-    public void attach(int pid) throws IOException {
-        checkProcess();
-        if (this.process != null) {
-            throw new IllegalStateException("Instance already started");
-        }
-        this.process = processBuilderFactory.newBuilder().attach(pid);
     }
 
     public String getName() {
-        return this.name;
+        return name;
     }
 
     public void setName(String name) {
+        throw new UnsupportedOperationException();
+    }
+
+    void doSetName(String name) {
         this.name = name;
     }
-    
+
     public boolean isRoot() {
-        return root;
+        return service.isInstanceRoot(name);
     }
 
     public String getLocation() {
-        return location;
+        return service.getInstanceLocation(name);
     }
 
     public void setLocation(String location) {
-        this.location = location;
-    }
-
-    public boolean exists() {
-        return new File(location).isDirectory();
+        throw new UnsupportedOperationException();
     }
 
     public int getPid() {
-        checkProcess();
-        return this.process != null ? this.process.getPid() : 0;
+        return service.getInstancePid(name);
     }
 
     public int getSshPort() {
-        try {
-            String loc = this.getConfiguration(new File(location, "etc/org.apache.karaf.shell.cfg"), "sshPort");
-            return Integer.parseInt(loc);
-        } catch (Exception e) {
-            return 0;
-        }
+        return service.getInstanceSshPort(name);
     }
 
     public void changeSshPort(int port) throws Exception {
-        checkProcess();
-        if (this.process != null) {
-            throw new IllegalStateException("Instance not stopped");
-        }
-        this.changeConfiguration(new File(location, "etc/org.apache.karaf.shell.cfg"),
-                "sshPort", Integer.toString(port));
+        service.changeInstanceSshPort(name, port);
     }
 
     public int getRmiRegistryPort() {
-        try {
-            String loc = this.getConfiguration(new File(location, "etc/org.apache.karaf.management.cfg"), "rmiRegistryPort");
-            return Integer.parseInt(loc);
-        } catch (Exception e) {
-            return 0;
-        }
+        return service.getInstanceRmiRegistryPort(name);
     }
 
     public void changeRmiRegistryPort(int port) throws Exception {
-        checkProcess();
-        if (this.process != null) {
-            throw new IllegalStateException("Instance not stopped");
-        }
-        this.changeConfiguration(new File(location, "etc/org.apache.karaf.management.cfg"),
-                "rmiRegistryPort", Integer.toString(port));
+        service.changeInstanceRmiRegistryPort(name, port);
     }
 
     public int getRmiServerPort() {
-        try {
-            String loc = this.getConfiguration(new File(location, "etc/org.apache.karaf.management.cfg"), "rmiServerPort");
-            return Integer.parseInt(loc);
-        } catch (Exception e) {
-            return 0;
-        }
+        return service.getInstanceRmiServerPort(name);
     }
 
     public void changeRmiServerPort(int port) throws Exception {
-        checkProcess();
-        if (this.process != null) {
-            throw new IllegalStateException("Instance not stopped");
-        }
-        this.changeConfiguration(new File(location, "etc/org.apache.karaf.management.cfg"),
-                "rmiServerPort", Integer.toString(port));
-    }
-
-    /**
-     * Change a configuration property in a given configuration file.
-     *
-     * @param configurationFile the configuration file where to update the configuration property.
-     * @param propertyName the property name.
-     * @param propertyValue the property value.
-     * @throws Exception if a failure occurs.
-     */
-    private void changeConfiguration(File configurationFile, String propertyName, String propertyValue) throws Exception {
-        Properties props = new Properties();
-        InputStream is = new FileInputStream(configurationFile);
-        try {
-            props.load(is);
-        } finally {
-            is.close();
-        }
-        props.put(propertyName, propertyValue);
-        OutputStream os = new FileOutputStream(configurationFile);
-        try {
-            props.save(os);
-        } finally {
-            os.close();
-        }
-    }
-
-    /**
-     * Read a given configuration file to get the value of a given property.
-     *
-     * @param configurationFile the configuration file where to lookup property.
-     * @param propertyName the property name to look for.
-     * @return the property value.
-     * @throws Exception in case of read failure.
-     */
-    private String getConfiguration(File configurationFile, String propertyName) throws Exception {
-        Properties props = loadPropertiesFile(configurationFile.toURI().toURL());
-        return props.getProperty(propertyName);
+        service.changeInstanceRmiServerPort(name, port);
     }
 
     public String getJavaOpts() {
-        return javaOpts;
+        return service.getInstanceJavaOpts(name);
     }
 
     public void changeJavaOpts(String javaOpts) throws Exception {
-        this.javaOpts = javaOpts;
-        this.service.saveState();
+        service.changeInstanceJavaOpts(name, javaOpts);
     }
 
-    public synchronized void start(String javaOpts) throws Exception {
-        checkProcess();
-        if (this.process != null) {
-            throw new IllegalStateException("Instance already started");
-        }
-        if (javaOpts == null || javaOpts.length() == 0) {
-            javaOpts = this.javaOpts;
-        }
-        if (javaOpts == null || javaOpts.length() == 0) {
-            javaOpts = "-server -Xmx512M -Dcom.sun.management.jmxremote";
-        }
-        String karafOpts = System.getProperty("karaf.opts", "");  
-        
-        File libDir = new File(System.getProperty("karaf.home"), "lib");
-        String classpath = createClasspathFromAllJars(libDir);
-        String endorsedDirs = getSubDirs(libDir, "endorsed");
-        String extDirs = getSubDirs(libDir, "ext");
-
-        String command = "\"" + ScriptUtils.getJavaCommandPath() + "\" " + javaOpts + " " + karafOpts
-                + " -Djava.util.logging.config.file=\"" + new File(location, "etc/java.util.logging.properties").getCanonicalPath() + "\""
-                + " -Djava.endorsed.dirs=\"" + endorsedDirs + "\""
-                + " -Djava.ext.dirs=\"" + extDirs + "\""
-                + " -Dkaraf.home=\"" + System.getProperty("karaf.home") + "\""
-                + " -Dkaraf.base=\"" + new File(location).getCanonicalPath() + "\""
-                + " -Dkaraf.startLocalConsole=false"
-                + " -Dkaraf.startRemoteShell=true"
-                + " -classpath " + classpath.toString()
-                + " org.apache.karaf.main.Main";
-        LOG.debug("Starting instance " + name + " with command: " + command);
-        this.process = processBuilderFactory.newBuilder()
-                        .directory(new File(location))
-                        .command(command)
-                        .start();
-        this.service.saveState();
-    }
-
-    private String getSubDirs(File libDir, String subDir) throws IOException {
-        File jreLibDir = new File(new File(System.getProperty("java.home"), "jre"), "lib");
-        File javaLibDir = new File(System.getProperty("java.home"), "lib");
-        String sep = System.getProperty("path.separator");
-        return new File(jreLibDir, subDir) + sep + new File(javaLibDir, subDir) + sep + new File(libDir, subDir).getCanonicalPath();
-    }
-
-    private String createClasspathFromAllJars(File libDir) throws IOException {
-        File[] jars = libDir.listFiles(new FilenameFilter() {
-            public boolean accept(File dir, String name) {
-                return name.endsWith(".jar");
-            }
-        });
-        StringBuilder classpath = new StringBuilder();
-        for (File jar : jars) {
-            if (classpath.length() > 0) {
-                classpath.append(System.getProperty("path.separator"));
-            }
-            classpath.append(jar.getCanonicalPath());
-        }
-        return classpath.toString();
-    }
-
-    public synchronized void stop() throws Exception {
-        checkProcess();
-        if (this.process == null) {
-            throw new IllegalStateException("Instance not started");
-        }
-        // Try a clean shutdown
-        cleanShutdown();
-        if (this.process != null) {
-            this.process.destroy();
-        }
-    }
-
-    public synchronized void destroy() throws Exception {
-        checkProcess();
-        if (this.process != null) {
-            throw new IllegalStateException("Instance not stopped");
-        }
-        deleteFile(new File(location));
-        this.service.forget(name);
-        this.service.saveState();
-    }
-
-    public synchronized String getState() {
-        int port = getSshPort();
-        if (!exists() || port <= 0) {
-            return ERROR;
-        }
-        checkProcess();
-        if (this.process == null) {
-            return STOPPED;
-        } else {
-            try {
-                Socket s = new Socket("localhost", port);
-                s.close();
-                return STARTED;
-            } catch (Exception e) {
-                // ignore
-            }
-            return STARTING;
-        }
-    }
-
-    protected void checkProcess() {
-        if (this.process != null) {
-            try {
-                if (!this.process.isRunning()) {
-                    this.process = null;
-                }
-            } catch (IOException e) {
-            }
-        }
-    }
-
-    protected void cleanShutdown() {
-        try {
-            File file = new File(new File(location, "etc"), CONFIG_PROPERTIES_FILE_NAME);
-            URL configPropURL = file.toURI().toURL();
-            Properties props = loadPropertiesFile(configPropURL);
-
-            String host = props.getProperty(KARAF_SHUTDOWN_HOST, "localhost");
-            
-            String shutdown = props.getProperty(KARAF_SHUTDOWN_COMMAND, DEFAULT_SHUTDOWN_COMMAND);
-            
-            int port = getShutDownPort(props);
-
-            // We found the port, try to send the command
-            if (port > 0) {
-                tryShutDownAndWait(host, shutdown, port, service.getStopTimeout());
-            }
-        } catch (Exception e) {
-            LOG.debug("Unable to cleanly shutdown instance", e);
-        }
-    }
-
-	private void tryShutDownAndWait(String host, String shutdownCommand, int port, long stopTimeout)
-			throws UnknownHostException, IOException, InterruptedException {
-		Socket s = new Socket(host, port);
-		s.getOutputStream().write(shutdownCommand.getBytes());
-		s.close();
-		long t = System.currentTimeMillis() + stopTimeout;
-		do {
-		    Thread.sleep(100);
-		    checkProcess();
-		} while (System.currentTimeMillis() < t && process != null);
-	}
-
-	private int getShutDownPort(Properties props) throws FileNotFoundException,
-			IOException {
-        
-        int port = Integer.parseInt(props.getProperty(KARAF_SHUTDOWN_PORT, "0"));
-
-		// Try to get port from port file
-		String portFile = props.getProperty(KARAF_SHUTDOWN_PORT_FILE);
-		if (port == 0 && portFile != null) {
-		    BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(portFile)));
-		    String portStr = r.readLine();
-		    port = Integer.parseInt(portStr);
-		    r.close();
-		}
-		return port;
-	}
-
-    protected static boolean deleteFile(File fileToDelete) {
-        if (fileToDelete == null || !fileToDelete.exists()) {
-            return true;
-        }
-        boolean result = true;
-        if (fileToDelete.isDirectory()) {
-            File[] files = fileToDelete.listFiles();
-            if (files == null) {
-                result = false;
-            } else {
-                for (int i = 0; i < files.length; i++) {
-                    File file = files[i];
-                    if (file.getName().equals(".") || file.getName().equals("..")) {
-                        continue;
-                    }
-                    if (file.isDirectory()) {
-                        result &= deleteFile(file);
-                    } else {
-                        result &= file.delete();
-                    }
-                }
-            }
-        }
-        result &= fileToDelete.delete();
-        return result;
-    }
-
-    protected Properties loadPropertiesFile(URL configPropURL) throws Exception {
-        // Read the properties file.
-        Properties configProps = new Properties();
-        InputStream is = null;
-        try {
-            configProps.put("karaf.base", new File(location).getCanonicalPath());
-            configProps.put("karaf.home", System.getProperty("karaf.home"));
-            configProps.put("karaf.data", new File(new File(location), "data").getCanonicalPath());
-            is = configPropURL.openConnection().getInputStream();
-            configProps.load(is);
-            return configProps;
-        } catch (Exception ex) {
-        	throw new RuntimeException("Error loading config properties from " + configPropURL, ex);
-        } finally {
-        	try {
-                if (is != null) is.close();
-            }
-            catch (IOException ex2) {
-                LOG.warn(ex2.getMessage(), ex2);
-            }
-        }
+    public void start(String javaOpts) throws Exception {
+        service.startInstance(name, javaOpts);
     }
 
-    public boolean isAttached() {
-        checkProcess();
-        return (process != null);
+    public void stop() throws Exception {
+        service.stopInstance(name);
     }
 
+    public void destroy() throws Exception {
+        service.destroyInstance(name);
+    }
 
-}
+    public String getState() throws Exception {
+        return service.getInstanceState(name);
+    }
+
+    public boolean isAttached() {
+        return getPid() != 0;
+    }
+}
\ No newline at end of file