View Javadoc

1   /*
2   Copyright (C) 2000 - 2007 Grid Systems, S.A.
3   
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License, version 2, as
6   published by the Free Software Foundation.
7   
8   This program is distributed in the hope that it will be useful,
9   but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12  
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  */
17  package com.gridsystems.config.modules.tomcat;
18  
19  import java.io.File;
20  import java.io.IOException;
21  import java.text.MessageFormat;
22  import java.util.ArrayList;
23  import java.util.Arrays;
24  import java.util.HashMap;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Properties;
28  import java.util.ResourceBundle;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  
33  import com.gridsystems.config.ConfiguratorModel;
34  import com.gridsystems.config.modules.jvm.JVMConfigurator;
35  import com.gridsystems.config.tools.IpVerifier;
36  import com.gridsystems.config.tools.Template;
37  import com.gridsystems.utils.NetUtils;
38  
39  /**
40   * Data model for the Tomcat configurator.
41   *
42   * @author Rodrigo Ruiz
43   * @author Xmas
44   * @version 1.0
45   */
46  public class TomcatConfigModel implements ConfiguratorModel {
47  
48    /**
49     * Allowed type of the IPs.
50     */
51    protected static final int ALLOWED_IP_TYPE = IpVerifier.IP_4_IP_6;
52  
53    /**
54     * Property key name for the IP Address field.
55     */
56    public static final String HOST_IP = "host.ip";
57  
58    /**
59     * Default shutdown port.
60     */
61    public static final int DEFAULT_SHUTDOWN_PORT = 9114;
62  
63    /**
64     * Default HTTP port.
65     */
66    public static final int DEFAULT_HTTP_PORT = 9112;
67  
68    /**
69     * Default HTTPS port.
70     */
71    public static final int DEFAULT_HTTPS_PORT = 9116;
72  
73    /**
74     * Default server restart exit code.
75     */
76    public static final int DEFAULT_RESTART_CODE = 0;
77  
78    /**
79     * Default server shutdown exit code.
80     */
81    public static final int DEFAULT_SHUTDOWN_CODE = 1;
82  
83    /**
84     * Default server restart enabled flag.
85     */
86    public static final boolean DEFAULT_RESTART_ENABLED = false;
87  
88    /**
89     * Default HTTPS enabled flag.
90     */
91    public static final boolean DEFAULT_HTTPS_ENABLED = false;
92  
93    /**
94     * Default keystore directory.
95     */
96    public static final String DEFAULT_KEYSTORE_DIR = "../conf/security";
97  
98    /**
99     * Default keystore password.
100    */
101   public static final String DEFAULT_KEYSTORE_PASS = "changeit2";
102 
103   /**
104    * Class logger.
105    */
106   private static Log log = LogFactory.getLog("TomcatConfigModel");
107 
108   /** Customizer bundle. */
109   private static ResourceBundle customizerBundle
110     = ResourceBundle.getBundle("ServerConfiguratorCustomizer");
111 
112   /**
113    * Gets the name of the product to Install.
114    * @return Name of the product to Install.
115    */
116   public static String getProductName() {
117     return getCustomizerString("Configurator.ProductName");
118   }
119 
120   /**
121    * Gets customizer string value from key.
122    * @param key Key of String.
123    * @return Value of customizer
124    */
125   public static String getCustomizerString(String key) {
126     return customizerBundle.getString(key);
127   }
128 
129   /**
130    * The IP address field value.
131    */
132   private String ip = null;
133 
134   /**
135    * Shutdown port.
136    */
137   private int fShutdownPort = DEFAULT_SHUTDOWN_PORT;
138 
139   /**
140    * Server restart enabled flag.
141    */
142   private boolean fRestartEnabled = DEFAULT_RESTART_ENABLED;
143 
144   /**
145    * Server restart exit code.
146    */
147   private int fRestartExitCode = DEFAULT_RESTART_CODE;
148 
149   /**
150    * Server shutdown exit code.
151    */
152   private int fShutdownExitCode = DEFAULT_SHUTDOWN_CODE;
153 
154   /**
155    * Keystore directory.
156    */
157   private File fKeystoreDir;
158 
159   /**
160    * Keystore password.
161    */
162   private String fKeystorePass;
163 
164   /**
165    * Previous keystore password.
166    */
167   private String fOldPassword;
168 
169   /**
170    * Truststore password.
171    */
172   private String fTruststorePass;
173 
174   /**
175    * Tomcat connector list.
176    */
177   private List<Connector> connectors = new ArrayList<Connector>();
178 
179   /**
180    * Default constructor.
181    */
182   public TomcatConfigModel() { }
183 
184   /**
185    * Creates a new instance.
186    *
187    * @param m The new model from which the old keystore password
188    *                      must be taken
189    */
190   public TomcatConfigModel(TomcatConfigModel m) {
191     if (m != null) {
192       this.connectors = m.connectors;
193       this.fKeystoreDir = m.fKeystoreDir;
194       this.fKeystorePass = m.fKeystorePass;
195       this.fOldPassword = m.fOldPassword;
196       this.fRestartEnabled = m.fRestartEnabled;
197       this.fRestartExitCode = m.fRestartExitCode;
198       this.fShutdownExitCode = m.fShutdownExitCode;
199       this.fShutdownPort = m.fShutdownPort;
200       this.fTruststorePass = m.fTruststorePass;
201       this.ip = m.ip;
202     }
203   }
204 
205   /**
206    * Gets the canonical path to the keystore directory.
207    *
208    * @return The canonical path to the keystore directory.
209    */
210   protected String getKeystorePath() {
211     try {
212       return fKeystoreDir.getCanonicalPath().replace('\\', '/');
213     } catch (IOException e) {
214       return fKeystoreDir.getAbsolutePath().replace('\\', '/');
215     }
216   }
217 
218   /**
219    * @see ConfiguratorModel#load()
220    */
221   public void load() {
222     JVMConfigurator jvmc = JVMConfigurator.getInstance();
223     // IP
224     if (this.ip == null || this.ip.length() == 0) {
225       this.ip = jvmc.getProperty(HOST_IP, null);
226       if (this.ip == null || this.ip.length() == 0) {
227         this.ip = NetUtils.getMachineIP();
228       }
229     }
230     // Other properties
231     fShutdownPort = jvmc.getIntProperty("tomcat.shutdown.port", DEFAULT_SHUTDOWN_PORT);
232     fRestartEnabled = jvmc.getBoolProperty("restart.enabled", DEFAULT_RESTART_ENABLED);
233     fRestartExitCode = jvmc.getIntProperty("exitcode.restart", DEFAULT_RESTART_CODE);
234     fShutdownExitCode = jvmc.getIntProperty("exitcode.shutdown", DEFAULT_SHUTDOWN_CODE);
235 
236     String path = jvmc.getProperty("keystore.dir", DEFAULT_KEYSTORE_DIR);
237     fKeystoreDir = new File(path);
238 
239     fKeystorePass = jvmc.getProperty("keystore.password", null);
240     if (fKeystorePass == null) {
241       fKeystorePass = DEFAULT_KEYSTORE_PASS;
242       fOldPassword = "changeit";
243     } else {
244       fOldPassword = fKeystorePass;
245     }
246 
247     fTruststorePass = jvmc.getProperty("truststore.password", null);
248     if (fTruststorePass == null) {
249       fTruststorePass = fKeystorePass;
250     }
251 
252     File f = new File("../conf/connectors.conf");
253     if (f.isFile()) {
254       try {
255         connectors = Connector.loadFromFile(f);
256       } catch (Exception e) {
257         log.error("Error parsing the connector list", e);
258       }
259     }
260     fixConnectors();
261   }
262 
263   /**
264    * {@inheritDoc}
265    */
266   public void store() throws IOException {
267     File f = new File("../conf/connectors.conf");
268     Connector.saveToFile(f, connectors);
269   }
270 
271   /**
272    * {@inheritDoc}
273    */
274   public void apply() throws IOException {
275     // General Error
276     if (this.connectors.size() == 0) {
277       ResourceBundle bundle;
278       bundle = ResourceBundle.getBundle(TomcatConfigurator.BUNDLE);
279       throw new IOException(bundle.getString("errors.general"));
280     }
281     Properties props = new Properties();
282     props.setProperty(HOST_IP, this.ip);
283     props.setProperty("http.port", Integer.toString(getHttpPort()));
284     props.setProperty("shutdown.port", Integer.toString(fShutdownPort));
285     props.setProperty("restart.enabled", fRestartEnabled ? "true" : "false");
286     props.setProperty("restart.exitcode", Integer.toString(fRestartExitCode));
287     props.setProperty("shutdown.exitcode", Integer.toString(fShutdownExitCode));
288 
289     // SSL support
290     String keystore = getKeystorePath() + "/keystore";
291     String password = fKeystorePass;
292     String truststore = getKeystorePath() + "/cacerts";
293     String trustpass = fTruststorePass;
294 
295     // Check that truststore does exist
296     File f = new File(truststore);
297     if (!f.exists()) {
298       truststore = null;
299       trustpass = null;
300     }
301     String xml = Connector.toXML(connectors, keystore, password, truststore, trustpass);
302 
303     props.setProperty("connectors", xml);
304 
305     // server.xml configuration file
306     applyTemplate(props, "../conf/template_server.xml", "template_server.xml",
307                          "../conf/server.xml");
308 
309     // kernel startup/shutdown script
310     String ext = (File.separatorChar == '\\') ? ".bat" : ".sh";
311     String src = "template_kernel" + (fRestartEnabled ? "HA" : "") + ext;
312     String dst = "kernel" + ext;
313 
314     applyTemplate(props, src, src, dst);
315 
316     // Set a properties to apply to template_ServerHA.cfg
317     Connector maidenPort = getMaidenPort();
318     Properties serverHaProperties = new Properties();
319     serverHaProperties.put(
320       "server.maiden.port.number", Integer.toString(maidenPort.getPort()));
321     serverHaProperties.put(
322       "server.maiden.port.protocol", maidenPort.getProtocol());
323     applyTemplate(serverHaProperties, "template_ServerHA.cfg",
324       "template_ServerHA.cfg", "ServerHA.cfg");
325 
326     // Keystore creation
327     if (isHttpsEnabled()) {
328       Properties p = new Properties();
329       p.setProperty("keystore.pass", fKeystorePass);
330       p.setProperty("keystore.oldPass", fOldPassword);
331       KeystoreUtils.createKeystores(fKeystoreDir, p);
332     }
333 
334     applyJVMConfiguration(maidenPort);
335 
336     // The current password has changed
337     fOldPassword = fKeystorePass;
338   }
339 
340   /**
341    * Applies the configuration for the Java Virtual Machine.
342    * @param maidenPort the Maiden port
343    */
344   private void applyJVMConfiguration(Connector maidenPort) {
345     // Changes to the JVM configurator are done AFTER keystore manipulation, to
346     // avoid inconsistencies in case of errors
347     JVMConfigurator jvmc = JVMConfigurator.getInstance();
348     jvmc.setProperty(
349       "server.maiden.port.number", Integer.toString(maidenPort.getPort()));
350     jvmc.setProperty(
351       "server.maiden.port.protocol", maidenPort.getProtocol());
352     jvmc.setProperty("tomcat.shutdown.port", Integer.toString(fShutdownPort));
353     jvmc.setProperty("restart.enabled", fRestartEnabled ? "true" : "false");
354     jvmc.setProperty("restart.exitcode", Integer.toString(fRestartExitCode));
355     jvmc.setProperty("shutdown.exitcode", Integer.toString(fShutdownExitCode));
356 
357     jvmc.setProperty("keystore.dir", getKeystorePath());
358     jvmc.setProperty("keystore.password", fKeystorePass);
359     jvmc.setProperty("truststore.password", fTruststorePass);
360     jvmc.setProperty(HOST_IP, this.ip);
361 
362     //File cacerts = new File(fKeystoreDir, "cacerts");
363     //jvmc.setProperty("javax.net.ssl.trustStore", cacerts.getAbsolutePath());
364     //jvmc.setProperty("javax.net.ssl.trustStorePassword", fTruststorePass);
365     jvmc.setProperty("java.awt.headless", "true");
366 
367     // Switch off the logs for Skaringa (this is, for Commons-Logging
368     //jvmc.setProperty("org.apache.commons.logging.Log",
369     //                 "org.apache.commons.logging.impl.SimpleLog");
370     //jvmc.setProperty("org.apache.commons.logging.simplelog.defaultlog", "fatal");
371   }
372 
373   /**
374    * Gets a template as a resource located at <code>res</code>, with
375    * working copy at <code>src</code>, and writes it at <code>dest</code>
376    * replacing the values specified at <code>props</code>.
377    *
378    * @param props The values to replace in the template
379    * @param src   The file where the template is located
380    * @param res   The resource path to use if src does not exist
381    * @param dest  The destination file
382    */
383   private void applyTemplate(Properties props, String src, String res, String dest) {
384     try {
385       Template t;
386       t = new Template(new File(src), this.getClass().getResource(res));
387       t.writeTo(props, new File(dest));
388     } catch (Exception e) {
389       e.printStackTrace();
390     }
391   }
392 
393   /**
394    * Gets the IP address of the host.
395    *
396    * @return a String with the IP address of the host.
397    */
398   public String getIp() {
399     return this.ip;
400   }
401 
402   /**
403    * Sets the IP address of the host.
404    *
405    * @param ip a String with the IP address of the host.
406    */
407   public void setIp(String ip) {
408     this.ip = ip;
409   }
410 
411   /**
412    * Gets the HTTP port.
413    *
414    * @return The HTTP port
415    */
416   public int getHttpPort() {
417     for (Iterator it = connectors.iterator(); it.hasNext();) {
418       Connector c = (Connector) it.next();
419       if ("Default HTTP".equals(c.getName())) {
420         return c.getPort();
421       }
422     }
423 
424     // Default HTTP connector not found!?
425     return ((Connector)connectors.get(0)).getPort();
426   }
427 
428   /**
429    * Gets the shutdown port.
430    *
431    * @return The shutdown port
432    */
433   public int getShutdownPort() {
434     return fShutdownPort;
435   }
436 
437   /**
438    * Gets the HTTPS port.
439    *
440    * @return The HTTPS port
441    */
442   public int getHttpsPort() {
443     for (Iterator it = connectors.iterator(); it.hasNext();) {
444       Connector c = (Connector) it.next();
445       if ("Default HTTPS".equals(c.getName())) {
446         return c.getPort();
447       }
448     }
449     return 0;
450   }
451 
452   /**
453    * Gets the port to be used by the Server Maiden.
454    *
455    * Gets the port to be used by the Server Maiden. It will try to return, by
456    * priority:<ol>
457    * <li>The "DefaultHTTP" port.</li>
458    * <li>The "DefaultHTTPS" port.</li>
459    * <li>Any other HTTP port.</li>
460    * <li>Any other HTTPS port.</li>
461    * </ol>
462    *
463    * @return the selected port.
464    */
465   public Connector getMaidenPort() {
466     Connector returnValue = null;
467     // Levels: 0 -> "Default HTTPS", 1 -> Unknown HTTP, 2-> Unknown HTTPS
468     int level = Integer.MAX_VALUE;
469     for (Iterator it = connectors.iterator(); it.hasNext();) {
470       Connector c = (Connector) it.next();
471       if ("DefaultHTTP".equals(c.getName())) {
472         // This is the most important port.
473         return c;
474       }
475       if ("DefaultHTTPS".equals(c.getName())) {
476         returnValue = c;
477         level = 0;
478       } else {
479         if (c.getProtocol().equalsIgnoreCase(Connector.HTTPS)) {
480           // Unknown HTTPS Port. It does not sustitute any other.
481           if (level > 2) {
482             returnValue = c;
483             level = 2;
484           }
485         } else {
486           // Unknown HTTP Port. Only sustitutes Unknown HTTPS ports.
487           if (level > 1) {
488             returnValue = c;
489             level = 1;
490           }
491         }
492       }
493     }
494     return returnValue;
495   }
496   /**
497    * Gets the "HTTPS enabled" flag value.
498    *
499    * @return The current "HTTPS enabled" flag value
500    */
501   public boolean isHttpsEnabled() {
502     for (Iterator it = connectors.iterator(); it.hasNext();) {
503       Connector c = (Connector) it.next();
504       if (c.getProtocol().equalsIgnoreCase(Connector.HTTPS)) {
505         return true;
506       }
507     }
508     return false;
509   }
510 
511   /**
512    * Gets the "Restart enabled" flag value.
513    *
514    * @return The current "Restart enabled" flag value
515    */
516   public boolean isRestartEnabled() {
517     return fRestartEnabled;
518   }
519 
520   /**
521    * Gets the restart exit code.
522    *
523    * @return The restart exit code
524    */
525   public int getRestartExitCode() {
526     return fRestartExitCode;
527   }
528 
529   /**
530    * Gets the shutdown exit code.
531    *
532    * @return The shutdown exit code
533    */
534   public int getShutdownExitCode() {
535     return fShutdownExitCode;
536   }
537 
538   /**
539    * Sets the port number for shutdown requests.
540    *
541    * @param port The port number
542    */
543   public void setShutdownPort(int port) {
544     this.fShutdownPort = port;
545   }
546 
547   /**
548    * Sets the port for shutdown requests.
549    *
550    * @param s The port number. The default value is 8085.
551    *          If s is not a valid number, the default value will be set.
552    */
553   public void setShutdownPort(String s) {
554     try {
555       fShutdownPort = Integer.parseInt(s);
556     } catch (Exception e) {
557       fShutdownPort = DEFAULT_SHUTDOWN_PORT;
558     }
559   }
560 
561   /**
562    * Enables or disables the restart control.
563    *
564    * @param enabled Whether or not restart control must be enabled
565    */
566   public void setRestartEnabled(boolean enabled) {
567     fRestartEnabled = enabled;
568   }
569 
570   /**
571    * Sets the exit code that will instruct the daemon to restart the server.
572    *
573    * @param exitCode the exit code for restarts
574    */
575   public void setRestartExitCode(int exitCode) {
576     fRestartExitCode = exitCode;
577   }
578 
579   /**
580    * Sets the exit code that will instruct the daemon to not restart the server.
581    *
582    * @param exitCode The exit code for shutdowns
583    */
584   public void setShutdownExitCode(int exitCode) {
585     fShutdownExitCode = exitCode;
586   }
587 
588   /**
589    * Gets the keystore directory.
590    *
591    * @return The keystore directory
592    */
593   public File getKeystoreDir() {
594     return this.fKeystoreDir;
595   }
596 
597   /**
598    * Sets the keystore directory.
599    *
600    * @param dir The keystore directory
601    */
602   public void setKeystoreDir(File dir) {
603     this.fKeystoreDir = dir;
604   }
605 
606   /**
607    * Gets the keystore password.
608    *
609    * @return The keystore password
610    */
611   public String getKeystorePassword() {
612     return this.fKeystorePass;
613   }
614 
615   /**
616    * Sets the keystore password.
617    *
618    * @param pass The keystore password
619    */
620   public void setKeystorePassword(String pass) {
621     this.fKeystorePass = pass;
622   }
623 
624   /**
625    * Gets the list of connectors.
626    *
627    * @return  the list of connectors
628    */
629   public Connector[] getConnectors() {
630     Connector[] list = new Connector[connectors.size()];
631     for (int i = 0; i < list.length; i++) {
632       list[i] = ((Connector) connectors.get(i)).copy();
633     }
634     return list;
635   }
636 
637   /**
638    * Sets the list of connectors.
639    *
640    * @param cc the list of connectors
641    * @throws Exception If a validation error occurs
642    */
643   public void setConnectors(Connector[] cc) throws Exception {
644     validate(cc);
645     connectors = Arrays.asList(cc);
646     //fixConnectors();
647   }
648 
649   /**
650    * Adds a connector to the list.
651    *
652    * @param c  the connector
653    */
654   public void addConnector(Connector c) {
655     connectors.add(0, c);
656   }
657 
658   /**
659    * Validate data of this Model.
660    *
661    * @param conns  the list of connectors to validate
662    * @throws Exception In case of invalid data
663    */
664   public void validate(List conns) throws Exception {
665     HashMap<String, Connector> map = new HashMap<String, Connector>();
666     for (Iterator it = conns.iterator(); it.hasNext();) {
667       Connector c = (Connector) it.next();
668       check(map, c);
669     }
670   }
671 
672   /**
673    * Validate data of this Model.
674    *
675    * @param conns  the list of connectors to validate
676    * @throws Exception In case of invalid data
677    */
678   public void validate(Connector[] conns) throws Exception {
679     HashMap<String, Connector> map = new HashMap<String, Connector>();
680     for (int i = 0; i < conns.length; i++) {
681       check(map, conns[i]);
682     }
683   }
684 
685   /**
686    * Validate data of this Model.
687    *
688    * @throws Exception In case of invalid data
689    */
690   public void validate() throws Exception {
691     if ((this.ip == null) || (this.ip.length() == 0)) {
692       log.error("IP is empty! Maybe a configuration error has happened");
693       ResourceBundle bundle = TomcatConfigurator.getInstance().getBundle();
694       throw new IOException(bundle.getString("errors.empty.ip"));
695     }
696     if (IpVerifier.isLoopbackAddress(this.ip, ALLOWED_IP_TYPE)) {
697       log.error("The IP is a loopback address! Maybe a configuration error has happened");
698       ResourceBundle bundle = TomcatConfigurator.getInstance().getBundle();
699       throw new IOException(bundle.getString("errors.loopback.ip"));
700     }
701     validate(connectors);
702   }
703 
704   /**
705    * Checks that the specified connector is compatible with the connectors
706    * in the passed map. If it is compatible, it is added to the map.
707    *
708    * @param map   the map of compatible connectors
709    * @param c     the connector to check
710    * @throws Exception  if the connector is not compatible with those in map
711    */
712   private void check(HashMap<String, Connector> map, Connector c) throws Exception {
713     if (c.getPort() == fShutdownPort) {
714       throw new IncompatiblePortException(c);
715     }
716 
717     String bindAddress = c.getAddress();
718     String name;
719     if (bindAddress == null || bindAddress.length() == 0) {
720       // Global binding: All connectors in this port must use the same protocol
721       for (Iterator it = map.values().iterator(); it.hasNext();) {
722         Connector cc = (Connector) it.next();
723         if (cc.getName().equals(c.getName())) {
724           ResourceBundle bundle = TomcatConfigurator.getInstance().getBundle();
725           String pattern = bundle.getString("errors.duplicatedPorts");
726           Object[] params = new Object[] {c.getName()};
727           throw new Exception(MessageFormat.format(pattern, params));
728         }
729         if (cc.getPort() == c.getPort()
730           && !cc.getProtocol().equalsIgnoreCase(c.getProtocol())) {
731           throw new IncompatiblePortException(cc);
732         }
733       }
734       // Fix bind address for name construction
735       name = "0.0.0.0:" + c.getPort();
736     } else {
737       name = bindAddress + ":" + c.getPort();
738 
739       // Specific binding: global or specific connector protocols must match
740       Connector cc = (Connector) map.get("0.0.0.0:" + c.getPort());
741       if (cc != null) {
742         cc = (Connector) map.get(name);
743       }
744       if (cc != null && !cc.getProtocol().equalsIgnoreCase(c.getProtocol())) {
745         throw new IncompatiblePortException(c);
746       }
747     }
748 
749     log.info("Checking port " + c.getPort());
750     if (!NetUtils.checkPort(c.getPort())) {
751       throw new PortInUseException(c);
752     }
753 
754     // All ok, adds this connector to the set
755     map.put(name, c);
756   }
757 
758   /**
759    * Ensures that there is at least one entry in the connectors list, and that entry
760    * is the "Default HTTP" connector.
761    */
762   private void fixConnectors() {
763     boolean hasDefault;
764 
765     if (connectors == null) {
766       connectors = new ArrayList<Connector>();
767       hasDefault = false;
768     } else {
769       if (connectors.size() == 0) {
770         hasDefault = false;
771       } else {
772         hasDefault = false;
773         int i = 0;
774         while (!hasDefault && (i < connectors.size())) {
775           Connector c = (Connector) connectors.get(i);
776           if (("Default HTTP".equals(c.getName())
777               && !c.getProtocol().equals(Connector.HTTPS))
778             || ("Default HTTPS".equals(c.getName())
779               && c.getProtocol().equals(Connector.HTTPS))) {
780             hasDefault = true;
781           }
782           i++;
783         }
784       }
785     }
786 
787     if (!hasDefault) {
788       Connector def = new Connector("Default HTTP", DEFAULT_HTTP_PORT, Connector.HTTP);
789       def.setUserCreated(false);
790       connectors.add(0, def);
791 
792       Connector sdef;
793       sdef = new Connector("Default HTTPS", DEFAULT_HTTPS_PORT, Connector.HTTPS);
794       sdef.setUserCreated(false);
795       connectors.add(1, sdef);
796     }
797   }
798 
799 
800 
801 }