Project

General

Profile

Download (24.1 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
 * Copyright (C) 2009 EDIT
4
 * European Distributed Institute of Taxonomy
5
 * http://www.e-taxonomy.eu
6
 *
7
 * The contents of this file are subject to the Mozilla Public License Version 1.1
8
 * See LICENSE.TXT at the top of this package for the full license terms.
9
 */
10

    
11
package eu.etaxonomy.cdm.server;
12

    
13
import static eu.etaxonomy.cdm.server.AssumedMemoryRequirements.KB;
14
import static eu.etaxonomy.cdm.server.CommandOptions.DATASOURCES_FILE;
15
import static eu.etaxonomy.cdm.server.CommandOptions.HELP;
16
import static eu.etaxonomy.cdm.server.CommandOptions.HTTP_PORT;
17
import static eu.etaxonomy.cdm.server.CommandOptions.JMX;
18
import static eu.etaxonomy.cdm.server.CommandOptions.LOG_DIR;
19
import static eu.etaxonomy.cdm.server.CommandOptions.WEBAPP;
20
import static eu.etaxonomy.cdm.server.CommandOptions.WEBAPP_CLASSPATH;
21
import static eu.etaxonomy.cdm.server.CommandOptions.WIN32SERVICE;
22

    
23
import java.io.BufferedReader;
24
import java.io.File;
25
import java.io.FileNotFoundException;
26
import java.io.FileOutputStream;
27
import java.io.IOException;
28
import java.io.InputStream;
29
import java.io.InputStreamReader;
30
import java.io.OutputStream;
31
import java.lang.management.ManagementFactory;
32
import java.net.URL;
33
import java.util.List;
34
import java.util.Properties;
35

    
36
import org.apache.commons.cli.CommandLine;
37
import org.apache.commons.cli.CommandLineParser;
38
import org.apache.commons.cli.GnuParser;
39
import org.apache.commons.cli.HelpFormatter;
40
import org.apache.commons.cli.ParseException;
41
import org.apache.commons.io.FileUtils;
42
import org.apache.log4j.Logger;
43
import org.apache.log4j.PatternLayout;
44
import org.apache.log4j.RollingFileAppender;
45
import org.eclipse.jetty.jmx.MBeanContainer;
46
import org.eclipse.jetty.security.HashLoginService;
47
import org.eclipse.jetty.server.Handler;
48
import org.eclipse.jetty.server.Server;
49
import org.eclipse.jetty.server.handler.ContextHandler;
50
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
51
import org.eclipse.jetty.util.log.Log;
52
import org.eclipse.jetty.webapp.WebAppClassLoader;
53
import org.eclipse.jetty.webapp.WebAppContext;
54

    
55
import eu.etaxonomy.cdm.server.instance.CdmInstance;
56
import eu.etaxonomy.cdm.server.instance.Configuration;
57
import eu.etaxonomy.cdm.server.instance.InstanceManager;
58
import eu.etaxonomy.cdm.server.instance.SharedAttributes;
59
import eu.etaxonomy.cdm.server.instance.Status;
60
import eu.etaxonomy.cdm.server.win32service.Win32Service;
61

    
62

    
63
/**
64
 * A bootstrap class for starting Jetty Runner using an embedded war.
65
 *
66
 * Recommended start options for the java virtual machine:
67
 * <pre>
68
 * -Xmx1024M
69
 *
70
 * -XX:PermSize=128m
71
 * -XX:MaxPermSize=192m
72
 *
73
 * -XX:+UseConcMarkSweepGC
74
 * -XX:+CMSClassUnloadingEnabled
75
 * -XX:+CMSPermGenSweepingEnabled
76
 * </pre>
77
 *
78
 * @version $Revision$
79
 */
80
public final class Bootloader {
81
    /**
82
     *
83
     */
84
    private static final String VERSION_PROPERTIES_FILE = "version.properties";
85

    
86
    //private static final String DEFAULT_WARFILE = "target/";
87

    
88

    
89

    
90
    private static final Logger logger = Logger.getLogger(Bootloader.class);
91

    
92
    private static final String DATASOURCE_BEANDEF_FILE = "datasources.xml";
93
    private static final String REALM_PROPERTIES_FILE = "cdm-server-realm.properties";
94

    
95
    private static final String USERHOME_CDM_LIBRARY_PATH = System.getProperty("user.home")+File.separator+".cdmLibrary"+File.separator;
96
    private static final String TMP_PATH = USERHOME_CDM_LIBRARY_PATH + "server" + File.separator;
97
    private static final String LOG_PATH = USERHOME_CDM_LIBRARY_PATH + "log" + File.separator;
98

    
99
    private static final String APPLICATION_NAME = "CDM Server";
100
    private static final String WAR_POSTFIX = ".war";
101

    
102
    private static final String CDMLIB_REMOTE_WEBAPP = "cdmlib-remote-webapp";
103
    private static final String CDMLIB_REMOTE_WEBAPP_VERSION = "cdmlib-remote-webapp.version";
104

    
105
    private static final String DEFAULT_WEBAPP_WAR_NAME = "default-webapp";
106
    private static final File DEFAULT_WEBAPP_TEMP_FOLDER = new File(TMP_PATH + DEFAULT_WEBAPP_WAR_NAME);
107
    private static final File CDM_WEBAPP_TEMP_FOLDER = new File(TMP_PATH + CDMLIB_REMOTE_WEBAPP);
108

    
109
    private final InstanceManager instanceManager = new InstanceManager(new File(USERHOME_CDM_LIBRARY_PATH, DATASOURCE_BEANDEF_FILE));
110

    
111
    public List<CdmInstance> getCdmInstances() {
112
        return instanceManager.getInstances();
113
    }
114

    
115
    public InstanceManager getInstanceManager(){
116
        return instanceManager;
117
    }
118

    
119
    private File cdmRemoteWebAppFile = null;
120
    private File defaultWebAppFile = null;
121

    
122
    private String logPath = null;
123

    
124
    private String webAppClassPath = null;
125

    
126
    private Server server = null;
127
    private final ContextHandlerCollection contexts = new ContextHandlerCollection();
128

    
129
    private CommandLine cmdLine;
130

    
131
    private boolean isRunningFromSource;
132

    
133
    private boolean isRunningfromTargetFolder;
134

    
135
    private boolean isRunningFromWarFile;
136

    
137
    /* thread save singleton implementation */
138

    
139
    private static Bootloader bootloader = new Bootloader();
140

    
141
    private Bootloader() {}
142

    
143
    /**
144
     * @return the thread save singleton instance of the Bootloader
145
     */
146
    public synchronized static Bootloader getBootloader(){
147
        return bootloader;
148
    }
149

    
150
    /* end of singleton implementation */
151

    
152

    
153
    public int writeStreamTo(final InputStream input, final OutputStream output, int bufferSize) throws IOException {
154
        int available = Math.min(input.available(), 256 * KB);
155
        byte[] buffer = new byte[Math.max(bufferSize, available)];
156
        int answer = 0;
157
        int count = input.read(buffer);
158
        while (count >= 0) {
159
            output.write(buffer, 0, count);
160
            answer += count;
161
            count = input.read(buffer);
162
        }
163
        return answer;
164
    }
165

    
166

    
167

    
168
    public void parseCommandOptions(String[] args) throws ParseException {
169
        CommandLineParser parser = new GnuParser();
170
        cmdLine = parser.parse( CommandOptions.getOptions(), args );
171

    
172
         // print the help message
173
         if(cmdLine.hasOption(HELP.getOpt())){
174
             HelpFormatter formatter = new HelpFormatter();
175
             formatter.setWidth(200);
176
             formatter.printHelp( "java .. ", CommandOptions.getOptions() );
177
             System.exit(0);
178
         }
179
    }
180

    
181

    
182
    private File extractWar(String warName) throws IOException, FileNotFoundException {
183
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
184
        String warFileName = warName + WAR_POSTFIX;
185

    
186
        // 1. find in classpath
187
        URL resource = classLoader.getResource(warFileName);
188
        if (resource == null) {
189
            logger.error("Could not find the " + warFileName + " on classpath!");
190

    
191
            File pomxml = new File("pom.xml");
192
            if(pomxml.exists()){
193
                // 2. try finding in target folder of maven project
194
                File warFile = new File("target" + File.separator + warFileName);
195
                logger.debug("looging for war file at " + warFile.getAbsolutePath());
196
                if (warFile.canRead()) {
197
                    resource = warFile.toURI().toURL();
198
                } else {
199
                    logger.error("Also could not find the " + warFileName + " in maven project, try excuting 'mvn install'");
200
                }
201
            }
202
        }
203

    
204
        if (resource == null) {
205
            // no way finding the war file :-(
206
            System.exit(1);
207
        }
208

    
209

    
210
        File warFile = new File(TMP_PATH, warName + "-" + WAR_POSTFIX);
211
        logger.info("Extracting " + warFileName + " to " + warFile + " ...");
212

    
213
        writeStreamTo(resource.openStream(), new FileOutputStream(warFile), 8 * KB);
214

    
215
        logger.info("Extracted " + warFileName);
216
        return warFile;
217
    }
218

    
219

    
220
    /**
221
     * MAIN METHOD
222
     *
223
     * @param args
224
     * @throws Exception
225
     */
226
    public static void main(String[] args) throws Exception {
227

    
228
        Bootloader bootloader = Bootloader.getBootloader();
229

    
230
        bootloader.parseCommandOptions(args);
231

    
232
        bootloader.startServer();
233
    }
234

    
235

    
236

    
237
    public void startServer() throws IOException,
238
            FileNotFoundException, Exception, InterruptedException {
239

    
240

    
241
        if(cmdLine.hasOption(LOG_DIR.getOpt())){
242
            logPath = cmdLine.getOptionValue(LOG_DIR.getOpt());
243
        } else {
244
            logPath = LOG_PATH;
245
        }
246

    
247

    
248
        //assure LOG_PATH exists
249
        File logPathFile = new File(logPath);
250
        if(!logPathFile.exists()){
251
            FileUtils.forceMkdir(new File(logPath));
252
        }
253

    
254
        //append logger
255
        configureFileLogger();
256

    
257
        logger.info("Starting "+APPLICATION_NAME);
258
        logger.info("Using  " + System.getProperty("user.home") + " as home directory. Can be specified by -Duser.home=<FOLDER>");
259

    
260
        //assure TMP_PATH exists and clean it up
261
        File tempDir = new File(TMP_PATH);
262
        if(!tempDir.exists() && !tempDir.mkdirs()){
263
            logger.error("Error creating temporary directory for webapplications " + tempDir.getAbsolutePath());
264
            System.exit(-1);
265
        } else {
266
            if(FileUtils.deleteQuietly(tempDir)){
267
                tempDir.mkdirs();
268
                logger.info("Old webapplications successfully cleared");
269
            }
270
        }
271
        tempDir = null;
272

    
273

    
274
        // WEBAPP options
275
        //   prepare web application files to run either from war files (production mode)
276
        //   or from source (development mode)
277
        if(cmdLine.hasOption(WEBAPP.getOpt())){
278

    
279
            cdmRemoteWebAppFile = new File(cmdLine.getOptionValue(WEBAPP.getOpt()));
280
            if(cdmRemoteWebAppFile.isDirectory()){
281
                logger.info("using user defined web application folder: " + cdmRemoteWebAppFile.getAbsolutePath());
282
            } else {
283
                logger.info("using user defined warfile: " + cdmRemoteWebAppFile.getAbsolutePath());
284
            }
285

    
286
            updateServerRunMode();
287

    
288
            // load the default-web-application from source if running in development mode mode
289
            if(isRunningFromWarFile){
290
                defaultWebAppFile = extractWar(DEFAULT_WEBAPP_WAR_NAME);
291
            } else {
292
                defaultWebAppFile = new File("./src/main/webapp");
293
            }
294

    
295
            if(isRunningFromSource){
296
                if(cmdLine.hasOption(WEBAPP_CLASSPATH.getOpt())){
297
                    String classPathOption = cmdLine.getOptionValue(WEBAPP_CLASSPATH.getOpt());
298
                    normalizeClasspath(classPathOption);
299
                }
300
            }
301
        } else {
302
            // read version number
303
            String version = readCdmRemoteVersion();
304
            cdmRemoteWebAppFile = extractWar(CDMLIB_REMOTE_WEBAPP + "-" + version);
305
            defaultWebAppFile = extractWar(DEFAULT_WEBAPP_WAR_NAME);
306
        }
307

    
308

    
309
        // HTTP Port
310
        int httpPort = 8080;
311
        if(cmdLine.hasOption(HTTP_PORT.getOpt())){
312
            try {
313
               httpPort = Integer.parseInt(cmdLine.getOptionValue(HTTP_PORT.getOpt()));
314
               logger.info(HTTP_PORT.getOpt()+" set to "+cmdLine.getOptionValue(HTTP_PORT.getOpt()));
315
           } catch (NumberFormatException e) {
316
               logger.error("Supplied portnumber is not an integer");
317
               System.exit(-1);
318
           }
319
        }
320

    
321
         if(cmdLine.hasOption(DATASOURCES_FILE.getOpt())){
322
             logger.error(DATASOURCES_FILE.getOpt() + " NOT JET IMPLEMENTED!!!");
323
         }
324

    
325
        verifySystemResources();
326

    
327
         // load the configured instances for the first time
328
        instanceManager.reLoadInstanceConfigurations();
329

    
330
        server = new Server(httpPort);
331
        server.addLifeCycleListener(instanceManager);
332

    
333
        // JMX support
334
        if(cmdLine.hasOption(JMX.getOpt())){
335
            logger.info("adding JMX support ...");
336
            MBeanContainer mBeanContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
337
            server.getContainer().addEventListener(mBeanContainer);
338
            mBeanContainer.addBean(Log.getLog());
339
            mBeanContainer.start();
340
        }
341

    
342
        if(cmdLine.hasOption(WIN32SERVICE.getOpt())){
343
            Win32Service win32Service = new Win32Service();
344
            win32Service.setServer(server);
345
            server.setStopAtShutdown(true);
346
            server.addBean(win32Service);
347
        }
348

    
349
        // add default servlet context
350
        logger.info("preparing default WebAppContext");
351
        WebAppContext defaultWebappContext = new WebAppContext();
352

    
353
        setWebApp(defaultWebappContext, defaultWebAppFile);
354
        defaultWebappContext.setContextPath("/");
355
        defaultWebappContext.setTempDirectory(DEFAULT_WEBAPP_TEMP_FOLDER);
356

    
357
        // configure security context
358
        // see for reference * http://docs.codehaus.org/display/JETTY/Realms
359
        //                   * http://wiki.eclipse.org/Jetty/Starting/Porting_to_Jetty_7
360
        HashLoginService loginService = new HashLoginService();
361
        loginService.setConfig(USERHOME_CDM_LIBRARY_PATH + REALM_PROPERTIES_FILE);
362
        defaultWebappContext.getSecurityHandler().setLoginService(loginService);
363

    
364
        // Important:
365
        // the defaultWebappContext MUST USE the super classloader
366
        // otherwise the status page (index.jsp) might not work
367
        defaultWebappContext.setClassLoader(this.getClass().getClassLoader());
368
        contexts.addHandler(defaultWebappContext);
369

    
370
        logger.info("setting contexts ...");
371
        server.setHandler(contexts);
372
        logger.info("starting jetty ...");
373
//        try {
374

    
375
            server.start();
376

    
377
//        } catch(org.springframework.beans.BeansException e){
378
//        	Throwable rootCause = null;
379
//        	while(e.getCause() != null){
380
//        		rootCause = e.getCause();
381
//        	}
382
//        	if(rootCause != null && rootCause.getClass().getSimpleName().equals("InvalidCdmVersionException")){
383
//
384
//        		logger.error("rootCause ----------->" + rootCause.getMessage());
385
////        		for(CdmInstanceProperties props : configAndStatus){
386
////        			if(props.getDataSourceName())
387
////        		}
388
//        	}
389
//        }
390

    
391
        if(cmdLine.hasOption(WIN32SERVICE.getOpt())){
392
            logger.info("jetty has started as win32 service");
393
        } else {
394
            server.join();
395
            logger.info(APPLICATION_NAME+" stopped.");
396
            System.exit(0);
397
        }
398
    }
399

    
400
    /**
401
     * @param classpath
402
     */
403
    private void normalizeClasspath(String classpath) {
404
        StringBuilder classPathBuilder = new StringBuilder((int) (classpath.length() * 1.2));
405
        String[] cpEntries = classpath.split("[\\:]");
406
        for(String cpEntry : cpEntries){
407
            classPathBuilder.append(',');
408
//            if(cpEntry.endsWith(".jar")){
409
//                classPathBuilder.append("jar:");
410
//            }
411
            classPathBuilder.append(cpEntry);
412
        }
413
        webAppClassPath = classPathBuilder.toString();
414
    }
415

    
416
    public String readCdmRemoteVersion() throws IOException {
417
        String version = "cdmlib version unreadable";
418
        InputStream versionInStream = Bootloader.class.getClassLoader().getResourceAsStream(VERSION_PROPERTIES_FILE);
419
        if (versionInStream != null){
420
            Properties versionProperties = new Properties();
421
            versionProperties.load(versionInStream);
422
            version = versionProperties.getProperty(CDMLIB_REMOTE_WEBAPP_VERSION, version);
423
        }
424
        return version;
425
    }
426

    
427

    
428

    
429
    private void verifySystemResources() {
430

    
431
        OsChecker osChecker = new OsChecker();
432
        if(osChecker.isLinux()){
433
            try {
434
                Process p = Runtime.getRuntime().exec(new String[] { "bash", "-c", "ulimit -n" });
435
                BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
436
                String line;
437
                StringBuilder response = new StringBuilder();
438
                     while ((line = in.readLine()) != null) {
439
                         response.append(line);
440
                     }
441
               logger.info("OS Limit (Linux): maximum number of open files: " + response);
442
            } catch (IOException e) {
443
                // TODO Auto-generated catch block
444
                e.printStackTrace();
445
            }
446
        } else {
447
            logger.info("verifySystemResources only implemented for linux");
448
        }
449
    }
450

    
451

    
452
    /**
453
     * Configures and adds a {@link RollingFileAppender} to the root logger
454
     *
455
     * The log files of the cdm-remote instances are configured by the
456
     * {@link eu.etaxonomy.cdm.remote.config.LoggingConfigurer}
457
     */
458
    private void configureFileLogger() {
459

    
460
        PatternLayout layout = new PatternLayout("%d %p [%c] - %m%n");
461
        try {
462
            String logFile = logPath + File.separator + "cdmserver.log";
463
            RollingFileAppender appender = new RollingFileAppender(layout, logFile);
464
            appender.setMaxBackupIndex(3);
465
            appender.setMaxFileSize("2MB");
466
            Logger.getRootLogger().addAppender(appender);
467
            logger.info("logging to :" + logFile);
468
        } catch (IOException e) {
469
            logger.error("Creating RollingFileAppender failed:", e);
470
        }
471
    }
472

    
473

    
474
    /**
475
     * Adds a new WebAppContext to the contexts of the running jetty instance.
476
     * <ol>
477
     * <li>Initialize WebAppContext:
478
     * <ol>
479
     * <li>set context path</li>
480
     * <li>set tmp directory</li>
481
     * <li>bind JndiDataSource</li>
482
     * <li>set web app context attributes</li>
483
     * <li>create and setup individual classloader for the instance</li>
484
     * </ol>
485
     * </li>
486
     * <li>
487
     * finally add the new webappcontext to the contexts of the jetty instance</li>
488
     * </ol>
489
     *
490
     * @param instance
491
     * @return the instance given as parameter of null in case the instance has
492
     *         {@link Status.#disabled} or if it is already added.
493
     * @throws IOException
494
     */
495
    public WebAppContext addCdmInstanceContext(CdmInstance instance) throws IOException {
496

    
497
        Configuration conf = instance.getConfiguration();
498
        if(!instance.isEnabled()){
499
            logger.info(conf.getInstanceName() + " is disabled, possibly due to JVM memory limitations");
500
            return null;
501
        }
502
        if(getContextFor(conf) != null){
503
            logger.info(conf.getInstanceName() + " is alreaddy added to the contexts - skipping");
504
            return null;
505
        }
506

    
507
        instance.setStatus(Status.initializing);
508
        logger.info("preparing WebAppContext for '"+ conf.getInstanceName() + "'");
509
        WebAppContext cdmWebappContext = new WebAppContext();
510

    
511
        cdmWebappContext.setContextPath(constructContextPath(conf));
512
        cdmWebappContext.setTempDirectory(CDM_WEBAPP_TEMP_FOLDER);
513

    
514
        if(!instance.bindJndiDataSource()){
515
            // a problem with the datasource occurred skip this webapp
516
            cdmWebappContext = null;
517
            logger.error("a problem with the datasource occurred -> skipping /" + conf.getInstanceName());
518
            instance.setStatus(Status.error);
519
            return cdmWebappContext;
520
        }
521

    
522
        cdmWebappContext.setAttribute(SharedAttributes.ATTRIBUTE_DATASOURCE_NAME, conf.getInstanceName());
523
        cdmWebappContext.setAttribute(SharedAttributes.ATTRIBUTE_JDBC_JNDI_NAME, conf.getJdbcJndiName());
524
        setWebApp(cdmWebappContext, getCdmRemoteWebAppFile());
525

    
526
        cdmWebappContext.setAttribute(SharedAttributes.ATTRIBUTE_CDM_LOGFILE,
527
                logPath + File.separator + "cdm-"
528
                        + conf.getInstanceName() + ".log");
529

    
530
        if( isRunningFromSource ){
531

    
532
            /*
533
             * when running the webapp from {projectpath} src/main/webapp we
534
             * must assure that each web application is using it's own
535
             * classloader thus we tell the WebAppClassLoader where the
536
             * dependencies of the webapplication can be found. Otherwise
537
             * the system classloader would load these resources.
538
             */
539
            WebAppClassLoader classLoader = new WebAppClassLoader(cdmWebappContext);
540
            if(webAppClassPath != null){
541
                logger.info("Running cdmlib-remote-webapp from source folder: Adding class path supplied by option '-" +  WEBAPP_CLASSPATH.getOpt() +" =" + webAppClassPath +"'  to WebAppClassLoader");
542
                classLoader.addClassPath(webAppClassPath);
543
            } else {
544
                throw new RuntimeException("Classpath cdmlib-remote-webapp for missing while running cdmlib-remote-webapp from source folder. Please supplied cdm-server option '-" +  WEBAPP_CLASSPATH.getOpt() +"");
545
            }
546
            cdmWebappContext.setClassLoader(classLoader);
547
        }
548

    
549
        contexts.addHandler(cdmWebappContext);
550
        instance.setWebAppContext(cdmWebappContext);
551
        cdmWebappContext.addLifeCycleListener(instance);
552
        instance.setStatus(Status.stopped);
553

    
554
        return cdmWebappContext;
555
    }
556

    
557
    /**
558
     * @param conf
559
     * @return
560
     */
561
    private String constructContextPath(Configuration conf) {
562
        return "/" + conf.getInstanceName();
563
    }
564

    
565
    /**
566
     * Removes the given instance from the contexts. If the instance is running
567
     * at the time of calling this method it will be stopped first.
568
     * The JndiDataSource and the webapplicationContext will be released and removed.
569
     *
570
     * @param instance the instance to be removed
571
     *
572
     * @throws Exception in case stopping the instance fails
573
     */
574
    public void removeCdmInstanceContext(CdmInstance instance) throws Exception {
575

    
576
        if(instance.getWebAppContext() != null){
577
            if(instance.getWebAppContext().isRunning()){
578
                try {
579
                    instance.getWebAppContext().stop();
580
                } catch (Exception e) {
581
                    instance.getProblems().add("Error while stopping instance: " + e.getMessage());
582
                    throw e;
583
                }
584
            }
585
            contexts.removeHandler(instance.getWebAppContext());
586
            instance.releaseWebAppContext();
587
        } else  {
588
            // maybe something went wrong before, try to find the potentially lost
589
            // contexts directly in the server
590
            ContextHandler handler = getContextFor(instance.getConfiguration());
591
            if(handler != null){
592
                contexts.removeHandler(handler);
593
            }
594
        }
595
        instance.unbindJndiDataSource();
596
    }
597

    
598
    /**
599
     * Sets the webapp specified by the <code>webApplicationResource</code> to
600
     * the given <code>context</code>.
601
     *
602
     * @param context
603
     * @param webApplicationResource the resource can either be a directory containing
604
     * a Java web application or *.war file.
605
     *
606
     */
607
    private void setWebApp(WebAppContext context, File webApplicationResource) {
608
        if(webApplicationResource.isDirectory()){
609
            context.setResourceBase(webApplicationResource.getAbsolutePath());
610
            logger.debug("setting directory " + webApplicationResource.getAbsolutePath() + " as webapplication");
611
        } else {
612
            context.setWar(webApplicationResource.getAbsolutePath());
613
            logger.debug("setting war file " + webApplicationResource.getAbsolutePath() + " as webapplication");
614
        }
615
    }
616

    
617
    private void updateServerRunMode() {
618
        String webappPathNormalized = cdmRemoteWebAppFile.getAbsolutePath().replace('\\', '/');
619
        isRunningFromSource =  webappPathNormalized.endsWith("src/main/webapp");
620
        isRunningfromTargetFolder = webappPathNormalized.endsWith("cdmlib-remote-webapp/target/cdmserver");
621
        isRunningFromWarFile = !(isRunningFromSource || isRunningfromTargetFolder);
622
    }
623

    
624

    
625
    public Server getServer() {
626
        return server;
627
    }
628

    
629
    public ContextHandler getContextFor(Configuration conf) {
630
        return getContextFor(constructContextPath(conf));
631
    }
632

    
633
    public ContextHandler getContextFor(String contextPath) {
634
        for( Handler handler : contexts.getHandlers()){
635
            if(handler instanceof ContextHandler){
636
                if(((ContextHandler)handler).getContextPath().equals(contextPath)){
637
                    return (ContextHandler)handler;
638
                }
639
            }
640
        }
641
        return null;
642
    }
643

    
644
    public ContextHandlerCollection getContexts() {
645
        return contexts;
646
    }
647

    
648
    /**
649
     * @return a File object pointing to the location of the cdmlib-remote-webapp
650
     */
651
    public File getCdmRemoteWebAppFile(){
652
        if(cdmRemoteWebAppFile == null){
653
            throw new RuntimeException("Invalid order of action. Server not yet started. The startServer() method must be called first. ");
654
        }
655
        return cdmRemoteWebAppFile;
656
    }
657
}
(2-2/5)