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.console.webmanager;
019    
020    import java.io.IOException;
021    import java.net.URI;
022    import java.util.ArrayList;
023    import java.util.Collections;
024    import java.util.Comparator;
025    import java.util.HashMap;
026    import java.util.List;
027    
028    import javax.portlet.ActionRequest;
029    import javax.portlet.ActionResponse;
030    import javax.portlet.PortletConfig;
031    import javax.portlet.PortletContext;
032    import javax.portlet.PortletException;
033    import javax.portlet.PortletRequest;
034    import javax.portlet.PortletRequestDispatcher;
035    import javax.portlet.RenderRequest;
036    import javax.portlet.RenderResponse;
037    import javax.portlet.WindowState;
038    
039    import org.apache.commons.logging.Log;
040    import org.apache.commons.logging.LogFactory;
041    import org.apache.geronimo.console.BasePortlet;
042    import org.apache.geronimo.console.util.PortletManager;
043    import org.apache.geronimo.gbean.AbstractName;
044    import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
045    import org.apache.geronimo.kernel.proxy.GeronimoManagedBean;
046    import org.apache.geronimo.management.geronimo.KeystoreException;
047    import org.apache.geronimo.management.geronimo.KeystoreInstance;
048    import org.apache.geronimo.management.geronimo.KeystoreManager;
049    import org.apache.geronimo.management.geronimo.NetworkConnector;
050    import org.apache.geronimo.management.geronimo.SecureConnector;
051    import org.apache.geronimo.management.geronimo.WebContainer;
052    import org.apache.geronimo.management.geronimo.WebManager;
053    import org.apache.geronimo.management.geronimo.WebManager.ConnectorAttribute;
054    import org.apache.geronimo.management.geronimo.WebManager.ConnectorType;
055    import org.apache.geronimo.crypto.KeystoreUtil;
056    
057    /**
058     * A portlet that lets you list, add, remove, start, stop, restart and edit web
059     * connectors (currently, either Tomcat or Jetty).
060     *
061     * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
062     */
063    public class ConnectorPortlet extends BasePortlet {
064        private final static Log log = LogFactory.getLog(ConnectorPortlet.class);
065        
066        public static final String PARM_CONTAINER_URI = "containerURI";
067        public static final String PARM_CONNECTOR_URI = "connectorURI";
068        public static final String PARM_MANAGER_URI = "managerURI";
069        public static final String PARM_MODE = "mode";
070        public static final String PARM_CONNECTOR_TYPE = "connectorType";
071        public static final String PARM_CONNECTOR_ATTRIBUTES = "connectorAttributes";
072        public static final String PARM_DISPLAY_NAME = "uniqueName";
073        public static final String PARM_SERVER = "server";
074    
075        private PortletRequestDispatcher normalView;
076        private PortletRequestDispatcher maximizedView;
077        private PortletRequestDispatcher helpView;
078        private PortletRequestDispatcher editConnectorView;
079    
080        public void processAction(ActionRequest actionRequest,
081                                  ActionResponse actionResponse) throws PortletException, IOException {
082            String submit = actionRequest.getParameter("submit");
083            if ("Cancel".equalsIgnoreCase(submit)) {
084                // User clicked on "Cancel" button in add/edit connector page
085                actionResponse.setRenderParameter(PARM_MODE, "list");
086                return;
087            }
088            
089            String mode = actionRequest.getParameter(PARM_MODE);
090            String managerURI = actionRequest.getParameter(PARM_MANAGER_URI);
091            String containerURI = actionRequest.getParameter(PARM_CONTAINER_URI);
092            if(managerURI != null) actionResponse.setRenderParameter(PARM_MANAGER_URI, managerURI);
093            if(containerURI != null) actionResponse.setRenderParameter(PARM_CONTAINER_URI, containerURI);
094            WebContainer webContainer  = null;
095            String server = null;
096            if(containerURI != null) {
097                webContainer = PortletManager.getWebContainer(actionRequest, new AbstractName(URI.create(containerURI)));
098                server = getWebServerType(webContainer.getClass());
099            } else {
100                server = "unknown";
101            }
102            actionResponse.setRenderParameter(PARM_SERVER, server);
103            if(mode.equals("new")) {
104                // User selected to add a new connector, need to show criteria portlet
105                actionResponse.setRenderParameter(PARM_MODE, "new");
106                String connectorType = actionRequest.getParameter(PARM_CONNECTOR_TYPE);
107                actionResponse.setRenderParameter(PARM_CONNECTOR_TYPE, connectorType);
108            } else if(mode.equals("add")) { // User just submitted the form to add a new connector
109                // Create and configure the connector
110                WebManager manager = PortletManager.getWebManager(actionRequest, new AbstractName(URI.create(managerURI)));
111                ConnectorType connectorType = new ConnectorType(actionRequest.getParameter(PARM_CONNECTOR_TYPE));
112                
113                String uniqueName = actionRequest.getParameter(PARM_DISPLAY_NAME);
114                actionResponse.setRenderParameter(PARM_DISPLAY_NAME, uniqueName);
115                // set the connector attributes from the form post
116                List<ConnectorAttribute> connectorAttributes = manager.getConnectorAttributes(connectorType);
117                for (ConnectorAttribute attribute : connectorAttributes) {
118                    String name = attribute.getAttributeName();
119                    String value = actionRequest.getParameter(name);
120                    
121                    // handle booelan type special
122                    if (attribute.getAttributeClass().equals(Boolean.class)) {
123                        // browser sends value of checked checkbox as "on" or "checked"
124                        if ("on".equalsIgnoreCase(value) || "checked".equalsIgnoreCase(value)) {
125                            value=Boolean.toString(true);
126                        } else {
127                            value=Boolean.toString(false);
128                        }
129                    }
130                    // set the string form of the attribute's value as submitted by the browser
131                    if (value == null || value.trim().length()<1) {
132                        // special case for KeystoreManager gbean
133                        if ("trustStore".equals(attribute.getAttributeName())) {
134                            attribute.setValue(null);
135                        }
136                    } else {
137                        attribute.setStringValue(value.trim());
138                    }
139                }
140                // create the connector gbean based on the configuration data
141                AbstractName newConnectorName = manager.getConnectorConfiguration(connectorType, connectorAttributes, webContainer, uniqueName);
142                
143                // set the keystore properties if its a secure connector
144                setKeystoreProperties(actionRequest, newConnectorName);
145                
146                // Start the connector
147                try {
148                    GeronimoManagedBean managedBean = PortletManager.getManagedBean(actionRequest, newConnectorName);
149                    managedBean.startRecursive();
150                } catch (Exception e) {
151                    log.error("Unable to start connector", e); //TODO: get into rendered page
152                }
153                actionResponse.setRenderParameter(PARM_MODE, "list");
154            } else if(mode.equals("save")) { // User just submitted the form to update a connector
155                // Get submitted values
156                //todo: lots of validation
157                String connectorURI = actionRequest.getParameter(PARM_CONNECTOR_URI);
158                // Identify and update the connector
159                AbstractName connectorName = new AbstractName(URI.create(connectorURI));
160                NetworkConnector connector = PortletManager.getNetworkConnector(actionRequest, connectorName);
161                if(connector != null) {
162                    WebManager manager = PortletManager.getWebManager(actionRequest, new AbstractName(URI.create(managerURI)));
163                    ConnectorType connectorType = manager.getConnectorType(connectorName);
164                    
165                    // set the connector attributes from the form post
166                    for (ConnectorAttribute attribute : manager.getConnectorAttributes(connectorType)) {
167                        String name = attribute.getAttributeName();
168                        String value = actionRequest.getParameter(name);
169                        
170                        // handle booelan type special
171                        if (attribute.getAttributeClass().equals(Boolean.class)) {
172                            // browser sends value of checked checkbox as "on" or "checked"
173                            if ("on".equalsIgnoreCase(value) || "checked".equalsIgnoreCase(value)) {
174                                value=Boolean.toString(true);
175                            } else {
176                                value=Boolean.toString(false);
177                            }
178                        }
179                        // set the string form of the attribute's value as submitted by the browser
180                        if (value == null || value.trim().length()<1) {
181                            // special case for KeystoreManager gbean
182                            if ("trustStore".equals(attribute.getAttributeName())) {
183                                setProperty(connector,name,null);
184                            }
185                        } else {
186                            // set the string value on the ConnectorAttribute so 
187                            // it can handle type conversion via getValue()
188                            try {
189                                attribute.setStringValue(value);
190                                setProperty(connector,name,attribute.getValue());
191                            } catch (Exception e) {
192                                log.error("Unable to set property " + attribute.getAttributeName(), e);
193                            }
194                        }
195                    }
196                    
197                    // set the keystore properties if its a secure connector
198                    setKeystoreProperties(actionRequest, connectorName);
199                }
200                actionResponse.setRenderParameter(PARM_MODE, "list");
201            } else if(mode.equals("start")) {
202                String connectorURI = actionRequest.getParameter(PARM_CONNECTOR_URI);
203                // work with the current connector to start it.
204                NetworkConnector connector = PortletManager.getNetworkConnector(actionRequest, new AbstractName(URI.create(connectorURI)));
205                if(connector != null) {
206                    try {
207                        ((GeronimoManagedBean)connector).startRecursive();
208                    } catch (Exception e) {
209                        log.error("Unable to start connector", e); //todo: get into rendered page somehow?
210                    }
211                }
212                else {
213                    log.error("Incorrect connector reference"); //Replace this with correct error processing
214                }
215                actionResponse.setRenderParameter(PARM_CONNECTOR_URI, connectorURI);
216                actionResponse.setRenderParameter(PARM_MODE, "list");
217            } else if(mode.equals("stop")) {
218                String connectorURI = actionRequest.getParameter(PARM_CONNECTOR_URI);
219                // work with the current connector to stop it.
220                NetworkConnector connector = PortletManager.getNetworkConnector(actionRequest, new AbstractName(URI.create(connectorURI)));
221                if(connector != null) {
222                    try {
223                        ((GeronimoManagedBean)connector).stop();
224                    } catch (Exception e) {
225                        log.error("Unable to stop connector", e); //todo: get into rendered page somehow?
226                    }
227                }
228                else {
229                    log.error("Incorrect connector reference"); //Replace this with correct error processing
230                }
231                actionResponse.setRenderParameter(PARM_CONNECTOR_URI, connectorURI);
232                actionResponse.setRenderParameter(PARM_MODE, "list");
233            } else if(mode.equals("restart")) {
234                String connectorURI = actionRequest.getParameter(PARM_CONNECTOR_URI);
235                // work with the current connector to restart it.
236                NetworkConnector connector = PortletManager.getNetworkConnector(actionRequest, new AbstractName(URI.create(connectorURI)));
237                if(connector != null) {
238                    try {
239                        ((GeronimoManagedBean)connector).stop();
240                        ((GeronimoManagedBean)connector).start();
241                    } catch (Exception e) {
242                        log.error("Unable to restart connector", e); //todo: get into rendered page somehow?
243                    }
244                } else {
245                    log.error("Incorrect connector reference"); //Replace this with correct error processing
246                }
247                actionResponse.setRenderParameter(PARM_CONNECTOR_URI, connectorURI);
248                actionResponse.setRenderParameter(PARM_MODE, "list");
249            } else if(mode.equals("edit")) {
250                String connectorURI = actionRequest.getParameter(PARM_CONNECTOR_URI);
251                actionResponse.setRenderParameter(PARM_CONNECTOR_URI, connectorURI);
252                actionResponse.setRenderParameter(PARM_MODE, "edit");
253    
254            } else if(mode.equals("delete")) { // User chose to delete a connector
255                String connectorURI = actionRequest.getParameter(PARM_CONNECTOR_URI);
256                PortletManager.getWebManager(actionRequest, new AbstractName(URI.create(managerURI))).removeConnector(new AbstractName(URI.create(connectorURI)));
257                actionResponse.setRenderParameter(PARM_MODE, "list");
258            }
259        }
260    
261        protected void doView(RenderRequest renderRequest,
262                              RenderResponse renderResponse) throws IOException, PortletException {
263            if (WindowState.MINIMIZED.equals(renderRequest.getWindowState())) {
264                return;
265            }
266            String mode = renderRequest.getParameter(PARM_MODE);
267            if(mode == null || mode.equals("")) {
268                mode = "list";
269            }
270    
271            if(mode.equals("list")) {
272                doList(renderRequest, renderResponse);
273            } else {
274                String managerURI = renderRequest.getParameter(PARM_MANAGER_URI);
275                String containerURI = renderRequest.getParameter(PARM_CONTAINER_URI);
276                if(managerURI != null) renderRequest.setAttribute(PARM_MANAGER_URI, managerURI);
277                if(containerURI != null) renderRequest.setAttribute(PARM_CONTAINER_URI, containerURI);
278    
279                WebContainer container = PortletManager.getWebContainer(renderRequest, new AbstractName(URI.create(containerURI)));
280                String server = getWebServerType(container.getClass());
281                renderRequest.setAttribute(PARM_SERVER, server);
282    
283                if(mode.equals("new")) {
284                    String connectorType = renderRequest.getParameter(PARM_CONNECTOR_TYPE);
285                    WebManager webManager = PortletManager.getWebManager(renderRequest, new AbstractName(URI.create(managerURI)));
286                    ConnectorType type = new ConnectorType(connectorType);
287                    List<ConnectorAttribute> connectorAttributes = webManager.getConnectorAttributes(type);
288                    sortConnectorAttributes(connectorAttributes);
289                    renderRequest.setAttribute(PARM_CONNECTOR_ATTRIBUTES, connectorAttributes);
290                    renderRequest.setAttribute(PARM_CONNECTOR_TYPE, connectorType);
291                    renderRequest.setAttribute(PARM_MODE, "add");
292                    populateEnumAttributes(renderRequest);
293                    editConnectorView.include(renderRequest, renderResponse);
294                } else if(mode.equals("edit")) {
295                    String connectorURI = renderRequest.getParameter(PARM_CONNECTOR_URI);
296                    NetworkConnector connector = PortletManager.getNetworkConnector(renderRequest, new AbstractName(URI.create(connectorURI)));
297                    if(connector == null) {
298                        doList(renderRequest, renderResponse);
299                    } else {
300                        AbstractName connectorName = new AbstractName(URI.create(connectorURI));
301                        String uniqueName = connectorName.getName().get("name").toString();
302                        renderRequest.setAttribute(PARM_DISPLAY_NAME, uniqueName);
303                        WebManager webManager = PortletManager.getWebManager(renderRequest, new AbstractName(URI.create(managerURI)));
304                        ConnectorType connectorType = webManager.getConnectorType(connectorName);
305                        List<ConnectorAttribute> connectorAttributes = webManager.getConnectorAttributes(connectorType);
306                        sortConnectorAttributes(connectorAttributes);
307                        
308                        // populate the connector attributes from the connector
309                        for (ConnectorAttribute attribute : connectorAttributes) {
310                            try {
311                                Object value = getProperty(connector, attribute.getAttributeName());
312                                attribute.setValue(value);
313                            } catch (IllegalArgumentException e) {
314                                log.error("Unable to retrieve value of property " + attribute.getAttributeName(), e);
315                            }
316                        }
317                        
318                        renderRequest.setAttribute(PARM_CONNECTOR_ATTRIBUTES, connectorAttributes);
319                        renderRequest.setAttribute(PARM_CONNECTOR_URI, connectorURI);
320                        // populate any enum type values.  the browser will render them in a
321                        // <SELECT> input for the attribute
322                        populateEnumAttributes(renderRequest);
323                        
324                        renderRequest.setAttribute(PARM_MODE, "save");
325                        editConnectorView.include(renderRequest, renderResponse);
326                    }
327                }
328            }
329    
330        }
331    
332        // sorts connector attributes alphabetically, required attributes listed first
333        private void sortConnectorAttributes(List<ConnectorAttribute> connectorAttributes) {
334            Collections.sort(connectorAttributes, new Comparator<ConnectorAttribute>() {
335                public int compare(ConnectorAttribute o1, ConnectorAttribute o2) {
336                    if (o1.isRequired()) {
337                        if (o2.isRequired()) {
338                            return o1.getAttributeName().compareTo(o2.getAttributeName());
339                        }
340                        return -1;
341                    }
342                    if (o2.isRequired()) {
343                        return 1;
344                    }
345                    return o1.getAttributeName().compareTo(o2.getAttributeName());
346                }
347            });
348        }
349    
350        private void doList(RenderRequest renderRequest, RenderResponse renderResponse) throws PortletException, IOException {
351            WebManager[] managers = PortletManager.getWebManagers(renderRequest);
352            List<ContainerInfo> all = new ArrayList<ContainerInfo>();
353            for (int i = 0; i < managers.length; i++) {
354                WebManager manager = managers[i];
355                AbstractName webManagerName = PortletManager.getNameFor(renderRequest, manager);
356                
357                WebContainer[] containers = (WebContainer[]) manager.getContainers();
358                for (int j = 0; j < containers.length; j++) {
359                    List<ConnectorInfo> beans = new ArrayList<ConnectorInfo>();
360                    WebContainer container = containers[j];
361                    AbstractName containerName = PortletManager.getNameFor(renderRequest, container);
362                    String id;
363                    if(containers.length == 1) {
364                        id = manager.getProductName();
365                    } else {
366                        id = manager.getProductName() + " (" + containerName.getName().get(NameFactory.J2EE_NAME) + ")";
367                    }
368                    ContainerInfo result = new ContainerInfo(id, webManagerName.toString(), containerName.toString());
369    
370                    for (NetworkConnector connector : manager.getConnectorsForContainer(container)) {
371                        ConnectorInfo info = new ConnectorInfo();
372                        AbstractName connectorName = PortletManager.getNameFor(renderRequest, connector);
373                        info.setConnectorURI(connectorName.toString());
374                        info.setDescription(PortletManager.getGBeanDescription(renderRequest, connectorName));
375                        info.setUniqueName((String)connectorName.getName().get(NameFactory.J2EE_NAME));
376                        info.setState(((GeronimoManagedBean)connector).getState());
377                        info.setPort(connector.getPort());
378                        try {
379                            info.setProtocol(connector.getProtocol());
380                        } catch (IllegalStateException e) {
381                            info.setProtocol("unknown");
382                        }
383                        beans.add(info);
384                    }
385                    result.setConnectors(beans);
386                    result.setConnectorTypes(manager.getConnectorTypes());
387                    all.add(result);
388                }
389            }
390            renderRequest.setAttribute("containers", all);
391            renderRequest.setAttribute("serverPort", new Integer(renderRequest.getServerPort()));
392    
393            if (WindowState.NORMAL.equals(renderRequest.getWindowState())) {
394                normalView.include(renderRequest, renderResponse);
395            } else {
396                maximizedView.include(renderRequest, renderResponse);
397            }
398        }
399    
400        public final static class ContainerInfo {
401            private String name;
402            private String managerURI;
403            private String containerURI;
404            private List connectorTypes;
405            private List connectors;
406    
407            public ContainerInfo(String name, String managerURI, String containerURI) {
408                this.name = name;
409                this.managerURI = managerURI;
410                this.containerURI = containerURI;
411            }
412    
413            public String getName() {
414                return name;
415            }
416    
417            public List getConnectorTypes() {
418                return connectorTypes;
419            }
420    
421            public void setConnectorTypes(List connectorTypes) {
422                this.connectorTypes = connectorTypes;
423            }
424    
425            public List getConnectors() {
426                return connectors;
427            }
428    
429            public void setConnectors(List connectors) {
430                this.connectors = connectors;
431            }
432    
433            public String getManagerURI() {
434                return managerURI;
435            }
436    
437            public String getContainerURI() {
438                return containerURI;
439            }
440        }
441    
442        protected void doHelp(RenderRequest renderRequest,
443                              RenderResponse renderResponse) throws PortletException, IOException {
444            helpView.include(renderRequest, renderResponse);
445        }
446    
447        public void init(PortletConfig portletConfig) throws PortletException {
448            super.init(portletConfig);
449            PortletContext pc = portletConfig.getPortletContext();
450            normalView = pc.getRequestDispatcher("/WEB-INF/view/webmanager/connector/normal.jsp");
451            maximizedView = pc.getRequestDispatcher("/WEB-INF/view/webmanager/connector/maximized.jsp");
452            helpView = pc.getRequestDispatcher("/WEB-INF/view/webmanager/connector/help.jsp");
453            editConnectorView = pc.getRequestDispatcher("/WEB-INF/view/webmanager/connector/editConnector.jsp");
454        }
455    
456        public void destroy() {
457            normalView = null;
458            maximizedView = null;
459            helpView = null;
460            editConnectorView = null;
461            super.destroy();
462        }
463    
464        public static boolean isValid(String s) {
465            return s != null && !s.equals("");
466        }
467        
468        // stash any 'enum' type values for attributes.  right now this is
469        // hardcoded, need to promote these to the ConnectorAttribute apis
470        private void populateEnumAttributes(PortletRequest request) {
471            HashMap<String,String[]> enumValues = new HashMap<String,String[]>();
472            
473            // provide the two possible values for secure protocol - TLS and SSL
474            enumValues.put("secureProtocol", new String[] { "TLS", "SSL" }); //jetty
475            enumValues.put("sslProtocol", new String[] { "TLS", "SSL" }); //tomcat
476            
477            // keystore and truststore types for tomcat
478            enumValues.put("keystoreType", KeystoreUtil.keystoreTypes.toArray(new String[0]));
479            enumValues.put("truststoreType", KeystoreUtil.keystoreTypes.toArray(new String[0]));
480    
481            // provide the three possible values for secure algorithm - Default, SunX509, and IbmX509 
482            enumValues.put("algorithm", new String[] { "Default", "SunX509", "IbmX509" });
483            
484            // provide the possible values for the keystore name
485            KeystoreManager mgr = PortletManager.getCurrentServer(request).getKeystoreManager();
486            KeystoreInstance[] stores = mgr.getUnlockedKeyStores();
487            String[] storeNames = new String[stores.length];
488            for (int i = 0; i < storeNames.length; i++) {
489                storeNames[i] = stores[i].getKeystoreName();
490            }
491            enumValues.put("keyStore", storeNames);
492            
493            // provide the possible values for the trust store name
494            KeystoreInstance[] trusts = mgr.getUnlockedTrustStores();
495            String[] trustNames = new String[trusts.length];
496            for (int i = 0; i < trustNames.length; i++) {
497                trustNames[i] = trusts[i].getKeystoreName();
498            }
499            enumValues.put("trustStore", trustNames);
500            
501            request.setAttribute("geronimoConsoleEnumValues", enumValues);
502        }
503        
504        // get the special keystore properties from the request and set them on the connector
505        // TODO: need a more generic way to handle this
506        private void setKeystoreProperties(PortletRequest request, AbstractName connectorName) throws PortletException {
507            String containerURI = request.getParameter(PARM_CONTAINER_URI);
508            WebContainer container = PortletManager.getWebContainer(request, new AbstractName(URI.create(containerURI)));
509            String server = getWebServerType(container.getClass());
510            NetworkConnector connector = PortletManager.getNetworkConnector(request, connectorName);
511    
512            // return if not a secure connector
513            if (!(connector instanceof SecureConnector)) {
514                return;
515            }
516            
517            // right now only jetty supports the KeystoreManager
518            if (server.equals(WEB_SERVER_JETTY)) {
519                String keyStore = request.getParameter("keyStore");
520                
521                // get the unlocked keystore object from the keystore managaer
522                // gbean and set its keyalias directly on the connector 
523                try {
524                    KeystoreInstance[] keystores = PortletManager.getCurrentServer(request)
525                            .getKeystoreManager().getKeystores();
526    
527                    String[] keys = null;
528                    for (int i = 0; i < keystores.length; i++) {
529                        KeystoreInstance keystore = keystores[i];
530                        if (keystore.getKeystoreName().equals(keyStore)) {
531                            keys = keystore.getUnlockedKeys(null);
532                        }
533                    }
534                    if (keys != null && keys.length == 1) {
535                        setProperty(connector, "keyAlias", keys[0]);
536                    } else {
537                        throw new PortletException("Cannot handle keystores with anything but 1 unlocked private key");
538                    }
539                } catch (KeystoreException e) {
540                    throw new PortletException(e);
541                }
542            }
543        }
544    }