View Javadoc
1   /**
2    * This file Copyright (c) 2008-2016 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.module.templatingkit.setup;
35  
36  import info.magnolia.cms.util.ClasspathResourcesUtil;
37  import info.magnolia.importexport.BootstrapUtil;
38  import info.magnolia.module.InstallContext;
39  import info.magnolia.module.delta.AbstractTask;
40  import info.magnolia.module.delta.TaskExecutionException;
41  import info.magnolia.module.resources.ResourceTypes;
42  import info.magnolia.module.resources.setup.InstallBinaryResourcesTask;
43  import info.magnolia.module.resources.setup.InstallTextResourceTask;
44  import info.magnolia.module.resources.setup.InstallTextResourcesTask;
45  import info.magnolia.module.templatingkit.resources.STKResourceModel;
46  
47  import java.io.IOException;
48  
49  import javax.jcr.ImportUUIDBehavior;
50  import javax.jcr.RepositoryException;
51  
52  import org.apache.commons.lang3.StringUtils;
53  
54  /**
55   * Installs all css files under <code>/templating-kit/themes/themeName/css</code> to the
56   * resources and the images under <code>/templating-kit/themes/themeName/img</code> to the
57   * dms while themeName is a property in the module descriptor.
58   */
59  public class ThemeInstallTask extends AbstractTask {
60  
61      protected static final String THEME_NAME_PROPERTY = "themeName";
62      protected static final String DEFAULT_THEME_PATH_PATTERN = "/templating-kit/themes/%s/%s/.*";
63  
64      /**
65       * We have to warn if we overwrite everything during an update
66       * but be quiet if this is a fresh installation.
67       */
68      boolean isUpdate;
69      private boolean stripExtensions;
70  
71      public ThemeInstallTask() {
72          this(false);
73      }
74  
75      public ThemeInstallTask(boolean isUpdate) {
76          this(isUpdate, false);
77      }
78  
79      /**
80       * @deprecated since 2.9.3 - use {@link #ThemeInstallTask(boolean)} instead due to file extension is required
81       * in order to avoid duplicate resources.
82       */
83      @Deprecated
84      public ThemeInstallTask(boolean isUpdate, boolean stripExtensions) {
85          super("Install theme", "Installs css, js files and images.");
86          this.isUpdate = isUpdate;
87          this.stripExtensions = stripExtensions;
88      }
89  
90      // the tasks are not build in the constructor as we need the themeName from the module definition
91      @Override
92      public void execute(final InstallContext ctx) throws TaskExecutionException {
93          final String themeName = getThemeName(ctx);
94  
95          ResourceNameFilter filter = new ResourceNameFilter(ctx.getCurrentModuleDefinition().getName(), themeName);
96  
97          final String[] resourcesToBootstrap = ClasspathResourcesUtil.findResources(filter);
98  
99          try {
100             if (resourcesToBootstrap != null) {
101                 BootstrapUtil.bootstrap(resourcesToBootstrap, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
102             }
103         } catch (IOException e) {
104             throw new TaskExecutionException("Could not bootstrap: " + e.getMessage(), e);
105         } catch (RepositoryException e) {
106             throw new TaskExecutionException("Could not bootstrap: " + e.getMessage(), e);
107         }
108 
109         new InstallTextResourcesTask("", "", InstallTextResourceTask.DEFAULT_ENCODING, String.format(DEFAULT_THEME_PATH_PATTERN, themeName, ResourceTypes.CSS_SUFFIX),
110                 ResourceTypes.PROCESSED_CSS, true, STKResourceModel.class.getName(), false, stripExtensions).execute(ctx);
111 
112         new InstallTextResourcesTask("", "", InstallTextResourceTask.DEFAULT_ENCODING, String.format(DEFAULT_THEME_PATH_PATTERN, themeName, ResourceTypes.JS_SUFFIX),
113                 ResourceTypes.PROCESSED_JS, true, STKResourceModel.class.getName(), false, stripExtensions).execute(ctx);
114 
115         new InstallBinaryResourcesTask("", "", String.format(DEFAULT_THEME_PATH_PATTERN, themeName, "img"), false, stripExtensions).execute(ctx);
116 
117         if (isUpdate && resourcesToBootstrap != null) {
118             String aggNames = "";
119             for (String name : resourcesToBootstrap) {
120                 aggNames = aggNames + StringUtils.substringAfterLast(StringUtils.removeEnd(name, ".xml"), ".") + ", ";
121             }
122             ctx.warn("Theme(s) " + StringUtils.removeEnd(aggNames, ", ") + " have been overwritten completely");
123         }
124     }
125 
126     protected String getThemeName(InstallContext ctx) {
127         return ctx.getCurrentModuleDefinition().getProperty(THEME_NAME_PROPERTY);
128     }
129 
130     /**
131      * Filter allowing only theme xml files to pass.
132      */
133     public class ResourceNameFilter implements info.magnolia.cms.util.ClasspathResourcesUtil.Filter {
134 
135         private String moduleName;
136 
137         private String themeName;
138 
139         public ResourceNameFilter(String moduleName, String themeName) {
140             this.moduleName = moduleName;
141             this.themeName = themeName;
142         }
143 
144         @Override
145         public boolean accept(String name) {
146             return name.startsWith("/mgnl-bootstrap/" + this.moduleName + "/config.modules.standard-templating-kit.config.themes.") && name.endsWith(".xml") && name.contains(this.themeName);
147         }
148     }
149 }