001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    
018    package org.apache.geronimo.deployment.plugin.factories;
019    
020    import java.io.IOException;
021    import java.util.Collection;
022    import java.util.Collections;
023    import java.util.HashMap;
024    import java.util.Map;
025    
026    import javax.enterprise.deploy.spi.DeploymentManager;
027    import javax.enterprise.deploy.spi.exceptions.DeploymentManagerCreationException;
028    import javax.enterprise.deploy.spi.factories.DeploymentFactory;
029    import javax.management.remote.JMXConnector;
030    import javax.management.remote.JMXConnectorFactory;
031    import javax.management.remote.JMXServiceURL;
032    
033    import org.apache.commons.logging.Log;
034    import org.apache.commons.logging.LogFactory;
035    import org.apache.geronimo.deployment.ModuleConfigurer;
036    import org.apache.geronimo.deployment.plugin.DisconnectedDeploymentManager;
037    import org.apache.geronimo.deployment.plugin.jmx.LocalDeploymentManager;
038    import org.apache.geronimo.deployment.plugin.jmx.RemoteDeploymentManager;
039    import org.apache.geronimo.kernel.KernelRegistry;
040    
041    /**
042     * Base implementation of JSR88 DeploymentFactory.
043     *
044     * This will create a DeploymentManager using a local Geronimo kernel
045     * to contain the GBeans that are responsible for deploying each module
046     * type.
047     *
048     * @version $Rev: 527918 $ $Date: 2007-04-12 09:04:16 -0400 (Thu, 12 Apr 2007) $
049     */
050    public class BaseDeploymentFactory implements DeploymentFactory {
051        private static final Log log = LogFactory.getLog(BaseDeploymentFactory.class);
052    
053        public static final String URI_PREFIX = "deployer:geronimo:";
054        private static final int DEFAULT_PORT = 1099;
055    
056        public BaseDeploymentFactory() {
057        }
058    
059        public String getDisplayName() {
060            return "Apache Geronimo";
061        }
062    
063        public String getProductVersion() {
064            return "1.0";
065        }
066    
067        public boolean handlesURI(String uri) {
068            return parseURI(uri) != null;
069        }
070    
071        private ConnectParams parseURI(String uri) {
072            uri = uri.trim();
073            if(!uri.startsWith(URI_PREFIX)) {
074                return null;
075            }
076            uri = uri.substring(URI_PREFIX.length());
077            int pos = uri.indexOf(":");
078            String protocol = pos == -1 ? uri : uri.substring(0, pos);
079            uri = pos == -1 ? "" : uri.substring(pos+1);
080            if(protocol.equals("jmx")) {
081                if(!uri.startsWith("//")) {
082                    return new ConnectParams(protocol, "localhost", DEFAULT_PORT);
083                }
084                uri = uri.substring(2);
085                pos = uri.indexOf(':');
086                if(pos == -1) {
087                    return new ConnectParams(protocol, uri.equals("") ? "localhost" : uri, DEFAULT_PORT);
088                }
089                if(uri.indexOf('/', pos+1) > -1) {
090                    return null;
091                }
092                if(uri.indexOf(':', pos+1) > -1) {
093                    return null;
094                }
095                String host = uri.substring(0, pos);
096                String port = uri.substring(pos+1);
097                try {
098                    return new ConnectParams(protocol, host.equals("") ? "localhost" : host, Integer.parseInt(port));
099                } catch (NumberFormatException e) {
100                    return null;
101                }
102            } else if(protocol.equals("inVM")) {
103                if(uri.startsWith("//")) {
104                    String kernel = uri.substring(2);
105                    return new ConnectParams(protocol, kernel, -1);
106                } else {
107                    return new ConnectParams(protocol,
108                            KernelRegistry.getSingleKernel() == null ? null : KernelRegistry.getSingleKernel().getKernelName(),
109                            -1);
110                }
111            } else return null;
112        }
113    
114        public DeploymentManager getDisconnectedDeploymentManager(String uri) throws DeploymentManagerCreationException {
115            if (!handlesURI(uri)) {
116                return null;
117            }
118            
119            Collection<ModuleConfigurer> moduleConfigurers = getModuleConfigurers();
120            return new DisconnectedDeploymentManager(moduleConfigurers);
121        }
122    
123        public DeploymentManager getDeploymentManager(String uri, String username, String password) throws DeploymentManagerCreationException {
124            ConnectParams params = parseURI(uri);
125            if (params == null) {
126                return null;
127            }
128    
129            try {
130                if (params.getProtocol().equals("jmx")) {
131                    return newRemoteDeploymentManager(username, password, params);
132                } else if(params.getProtocol().equals("inVM")) {
133                    return new LocalDeploymentManager(KernelRegistry.getKernel(params.getHost()));
134                } else {
135                    throw new DeploymentManagerCreationException("Invalid URI: " + uri);
136                }
137            } catch (RuntimeException e) {
138                // some DeploymentManagerFactories suppress unchecked exceptions - log and rethrow
139                log.error(e.getMessage(), e);
140                throw e;
141            } catch (Error e) {
142                // some DeploymentManagerFactories suppress unchecked exceptions - log and rethrow
143                log.error(e.getMessage(), e);
144                throw e;
145            }
146        }
147    
148        protected Collection<ModuleConfigurer> getModuleConfigurers() throws DeploymentManagerCreationException {
149            return Collections.EMPTY_LIST;
150        }
151    
152        protected DeploymentManager newRemoteDeploymentManager(String username, String password, ConnectParams params) throws DeploymentManagerCreationException, AuthenticationFailedException {
153            Map environment = new HashMap();
154            String[] credentials = new String[]{username, password};
155            environment.put(JMXConnector.CREDENTIALS, credentials);
156            environment.put(JMXConnectorFactory.DEFAULT_CLASS_LOADER, BaseDeploymentFactory.class.getClassLoader());
157            try {
158                JMXServiceURL address = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://"+params.getHost()+":"+params.getPort()+"/JMXConnector");
159                JMXConnector jmxConnector = JMXConnectorFactory.connect(address, environment);
160                RemoteDeploymentManager manager = getRemoteDeploymentManager();
161                manager.init(jmxConnector, params.getHost());
162                if(!manager.isSameMachine()) {
163                    manager.setAuthentication(username, password);
164                }
165                return manager;
166            } catch (IOException e) {
167                throw (DeploymentManagerCreationException)new DeploymentManagerCreationException(e.getMessage()).initCause(e);
168            } catch (SecurityException e) {
169                throw (AuthenticationFailedException) new AuthenticationFailedException("Invalid login.").initCause(e);
170            }
171        }
172    
173        protected RemoteDeploymentManager getRemoteDeploymentManager() throws DeploymentManagerCreationException {
174            Collection<ModuleConfigurer> moduleConfigurers = getModuleConfigurers();
175            return new RemoteDeploymentManager(moduleConfigurers);
176        }
177    
178        private final static class ConnectParams {
179            private String protocol;
180            private String host;
181            private int port;
182    
183            public ConnectParams(String protocol, String host, int port) {
184                this.protocol = protocol;
185                this.host = host;
186                this.port = port;
187            }
188    
189            public String getProtocol() {
190                return protocol;
191            }
192    
193            public String getHost() {
194                return host;
195            }
196    
197            public int getPort() {
198                return port;
199            }
200    
201            public String toString() {
202                return protocol+" / "+host+" / "+port;
203            }
204        }
205    
206    }