source: branches/2.15-stable/www/admin/plugindefinitions/auto_install.jsp @ 5315

Last change on this file since 5315 was 5315, checked in by Nicklas Nordborg, 13 years ago

Fixes #1484: Plug-in installation wizard doesn't work in Internet Explorer 8

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 20.3 KB
Line 
1<%-- $Id: auto_install.jsp 5315 2010-04-19 05:46:06Z nicklas $
2  ------------------------------------------------------------------
3  Copyright (C) 2007 Johan Enell, Nicklas Nordborg
4
5  This file is part of BASE - BioArray Software Environment.
6  Available at http://base.thep.lu.se/
7
8  BASE is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License
10  as published by the Free Software Foundation; either version 3
11  of the License, or (at your option) any later version.
12
13  BASE is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  GNU General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with BASE. If not, see <http://www.gnu.org/licenses/>.
20  ------------------------------------------------------------------
21
22
23  @author Martin
24  @version 2.5
25--%>
26<%@ page session="false"
27  import="net.sf.basedb.core.Application"
28  import="net.sf.basedb.core.DbControl"
29  import="net.sf.basedb.core.Item"
30  import="net.sf.basedb.core.ItemContext"
31  import="net.sf.basedb.core.Include"
32  import="net.sf.basedb.core.ItemNotFoundException"
33  import="net.sf.basedb.core.ItemQuery"
34  import="net.sf.basedb.core.PluginDefinition"
35  import="net.sf.basedb.core.PluginConfiguration"
36  import="net.sf.basedb.core.SessionControl"
37  import="net.sf.basedb.core.query.Hql"
38  import="net.sf.basedb.core.query.Restrictions"
39  import="net.sf.basedb.core.query.Expressions"
40  import="net.sf.basedb.util.FileUtil"
41  import="net.sf.basedb.util.RegexpFileFilter"
42  import="net.sf.basedb.util.JarClassLoader"
43  import="net.sf.basedb.util.PluginInfo"
44  import="net.sf.basedb.util.PluginConfigInfo"
45  import="net.sf.basedb.util.Values"
46  import="net.sf.basedb.util.Tree"
47  import="net.sf.basedb.clients.web.Base"
48  import="net.sf.basedb.clients.web.util.HTML"
49  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
50  import="java.util.Collections"
51  import="java.util.List"
52  import="java.util.LinkedList"
53  import="java.util.Iterator"
54  import="java.io.FileFilter"
55%>
56<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
57<%@ taglib prefix="t" uri="/WEB-INF/tab.tld" %>
58<%!
59
60private void addDirectory(DbControl dc, Tree<Object> tree, java.io.File directory)
61  throws Exception
62{
63  FileFilter jarFilter = new RegexpFileFilter(".*\\.jar", null);
64  List<java.io.File> jarFiles = FileUtil.findFiles(directory, jarFilter);
65  for (java.io.File file : jarFiles)
66  {
67    addPluginJarFile(dc, tree, file);
68  }
69}
70
71private void addPluginJarFile(DbControl dc, Tree<Object> tree, java.io.File file)
72  throws Exception
73{
74  try
75  {
76    List<PluginInfo> plugins = PluginInfo.loadFromJar(file);
77    if (plugins != null && plugins.size() > 0)
78    {
79      Tree.Entry<Object> jarEntry = tree.getRootEntry().addChild(file);
80      for (PluginInfo pluginInfo : plugins)
81      {
82        pluginInfo.checkInstallation(dc);
83        Tree.Entry<Object> pluginEntry = jarEntry.addChild(pluginInfo);
84        List<PluginConfigInfo> configs = pluginInfo.getConfigurations();
85        if (configs != null)
86        {
87          for (PluginConfigInfo configInfo : configs)
88          {
89            configInfo.checkInstallation(dc);
90            pluginEntry.addChild(configInfo);
91          }
92        }
93      }
94    }
95  }
96  catch (Exception ex)
97  {
98    Tree.Entry<Object> jarEntry = tree.getRootEntry().addChild(file);
99    jarEntry.addChild(ex);
100  }
101}
102String generateJoustTree(Tree<Object> tree)
103{
104  StringBuilder sb = new StringBuilder();
105  Tree.Entry<Object> rootEntry = tree.getRootEntry();
106  Iterator<Tree.Entry<Object>> it = tree.entryIterator();
107  while (it.hasNext())
108  {
109    Tree.Entry<Object> entry = it.next();
110    Tree.Entry<Object> parentEntry = entry.getParent();
111    Object node = entry.getNode();
112    if (node == null) continue;
113    int joustId = System.identityHashCode(entry);
114
115    String name = node.toString();
116    String folderIcon = "";
117    boolean open = false;
118    sb.append("var node").append(joustId).append(" = ");
119    if (parentEntry == rootEntry)
120    {
121      sb.append("JoustMenu.addMenuItem(-1");
122    }
123    else
124    {
125      String parentVar = "node" + System.identityHashCode(parentEntry);
126      sb.append("JoustMenu.addChildItem(").append(parentVar);
127    }
128
129    if (node instanceof java.io.File)
130    {
131      java.io.File file = (java.io.File)node;
132      name = file.getName();
133      folderIcon = "JarFile";
134      Throwable error = null;
135      int numUpdated = 0;
136      int numInstalled = 0;
137      for (Tree.Entry<Object> child : entry.getChildren())
138      {
139        if (child.getNode() instanceof PluginInfo)
140        {
141          PluginInfo info = (PluginInfo)child.getNode();
142          if (!info.inSameJarFile() || info.hasDifferentVersion()) 
143          {
144            numUpdated++;
145          }
146          else
147          {
148            numInstalled++;
149          }
150        }
151        else if (child.getNode() instanceof Throwable)
152        {
153          error = (Throwable)child.getNode();
154        }
155      }
156      if (error != null)
157      {
158        name += " (" + error.getMessage() + ")";
159        folderIcon = "JarFileError";
160      }
161      else if (numUpdated > 0)
162      {
163        name += " (" + numUpdated + " new";
164        if (numInstalled > 0) name += "; " + numInstalled + " existing";
165        name += ")";
166        open = true;
167      }
168      else
169      {
170        name += " (already installed)";
171      }
172    }
173    else if (node instanceof PluginInfo)
174    {
175      PluginInfo info = (PluginInfo)node;
176      name = info.getAbout().getName();     
177      if ( info.isDenied() || 
178          (info.inSameJarFile() && !info.hasDifferentVersion()))
179      {
180        folderIcon = "PluginDisabled";
181      }
182      else if (info.isInstalled())
183      {
184        folderIcon = "PluginWarning";
185      }
186      else
187      {
188        folderIcon = "Plugin";
189      }
190    }
191    else if (node instanceof PluginConfigInfo)
192    {
193      PluginConfigInfo info = (PluginConfigInfo)node;
194      name = info.getName();
195      if (info.exists())
196      {
197        folderIcon = "ConfigurationWarning";
198      }
199      else
200      {
201        folderIcon = "Configuration";
202      }
203    }
204    else if (node instanceof Throwable)
205    {
206      Throwable t = (Throwable)node;
207      name = t.toString();
208      folderIcon = "Error";
209    }
210   
211    sb.append(",'").append(folderIcon).append("'");
212    sb.append(",'").append(HTML.javaScriptEncode(name)).append("'");
213    sb.append(", null, '', '").append(joustId).append("');\n");
214    if (open)
215    {
216      sb.append("JoustMenu.menuItems[node").append(joustId).append("].isOpen = true;\n");
217    }
218  }
219
220  return sb.toString();
221}
222
223private String getInfoMessage(PluginInfo info, int id)
224{
225  StringBuilder message = new StringBuilder();
226  message.append("<div id=\"info."+id+"\" class=\"postit\" style=\"width:500px; display:none;\">");
227 
228  if (!info.inSameJarFile())
229  {
230    message.append("<b>").append("Installed Jar: ").append("</b>");
231    String oldjarpath = info.getJarPathInDatabase();
232    message.append(oldjarpath).append("<br><b>New </b>");   
233  }
234 
235  message.append("<b>").append("Jar: ").append("</b>");
236  String jarpath = info.getJarPath();
237  message.append(jarpath).append("<br>");
238   
239  message.append("<b>").append("Class: ").append("</b>");
240  message.append(HTML.encodeTags(info.getClassName())).append("<br>");
241  if (info.isInstalled() && info.hasDifferentVersion())
242  {
243    message.append("<b>").append("Version: ").append("</b>");
244    message.append(HTML.encodeTags(info.getAbout().getVersion())).append("&nbsp;&nbsp;");
245   
246    message.append("(<i>").append("Installed version: ").append("</i>");
247    message.append(HTML.encodeTags(info.getVersionInDatabase())).append(")<br>");
248       
249  }
250  else
251  {
252    message.append("<b>").append("Version: ").append("</b>");
253    message.append(HTML.encodeTags(info.getAbout().getVersion())).append("<br>");
254  }
255 
256  message.append("<b>").append("Works with: ").append("</b>");
257  message.append("BASE ").append(info.getMinBaseVersion()).append(" and higher").append("<br>");
258 
259  message.append("<b>").append("Description: ").append("</b>");
260  message.append(HTML.encodeTags(info.getAbout().getDescription())).append("<br>");
261  message.append("</div>");
262  return message.toString();
263}
264%>
265<%
266final Item itemType = Item.PLUGINDEFINITION;
267final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
268final ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, null, null);
269final String ID = sc.getId();
270final float scale = Base.getScale(sc);
271final DbControl dc = sc.newDbControl();
272
273try
274{
275  String title = "Plugin autoinstaller";
276  String tt = cc.getPropertyValue("trusted");
277  String up = cc.getPropertyValue("usePermissions");
278  String aie = cc.getPropertyValue("allowImmediateExection");
279  boolean isTrusted = tt == null ? true : Values.getBoolean(tt);
280  boolean usePermissions = up == null ? false : Values.getBoolean(up);
281  Boolean allowImmediateExecution = aie == null ? null : Values.getBoolean(aie);
282  boolean scanPluginDir = Values.getBoolean(request.getParameter("plugindir"));
283  boolean scanExtensionsDir = Values.getBoolean(request.getParameter("extensionsdir"));
284 
285  java.io.File pluginDir = Application.getNonCorePluginDirectory();
286  java.io.File extensionsDir = new java.io.File(application.getRealPath(ExtensionsControl.EXTENSIONS_URL));
287  Tree<Object> plugins = new Tree<Object>(null);
288  if (scanPluginDir) addDirectory(dc, plugins, pluginDir);
289  if (scanExtensionsDir) addDirectory(dc, plugins, extensionsDir);
290  %>
291  <base:page type="popup" title="<%=title%>">
292  <base:head scripts="tabcontrol.js,newjoust.js" styles="tabcontrol.css">
293    <script language="JavaScript">
294   
295    // Submit the form
296    function saveSettings(install)
297    {
298      var frm = document.forms['autoinstall'];
299      frm.submit();
300    }
301    function installAll(jarFile)
302    {
303      var frm = document.forms['autoinstall'];
304      for (var i = 0; i < frm.elements.length; i++)
305      {
306        var element = frm[i];
307        if (element.name.indexOf(jarFile) == 0 && element.type == 'select-one' && !element.disabled)
308        {
309          element.selectedIndex = element.options.length-1;
310          pluginOnChange(element);
311        }
312      }
313    }
314
315    function pluginOnChange(list)
316    {
317      var selected = list[list.selectedIndex].value;
318      var configOption = selected == 'plugin+confs' ? 1 : 0;
319      var frm = document.forms['autoinstall'];
320      var pluginClass = list.name.substring(list.name.indexOf(':')+1);
321      for (var i = 0; i < frm.elements.length; i++)
322      {
323        var element = frm[i];
324        if (element.name.indexOf(pluginClass+":config") == 0 && element.type == 'select-one' && !element.disabled)
325        {
326          Forms.selectListOption(element, configOption);
327        }
328      }   
329    }
330
331    function configOnChange(list)
332    {
333      var selected = list[list.selectedIndex].value;
334      if (selected == 0) return;
335      var frm = document.forms['autoinstall'];
336      var pluginClass = list.name.substring(0, list.name.indexOf(':'));
337      for (var i = 0; i < frm.elements.length; i++)
338      {
339        var element = frm[i];
340        if (element.name.indexOf(pluginClass) > 0 && element.type == 'select-one' && !element.disabled)
341        {
342          Forms.selectListOption(element, 'plugin+confs');
343        }
344      }   
345     
346    }
347
348    function toggleInformation(pluginId)
349    {
350      var infodiv = document.getElementById('info.'+pluginId);
351      if (infodiv.style.display == 'block')
352      {
353        infodiv.style.display = 'none';       
354      }
355      else if (infodiv.style.display == 'none')
356      {
357        infodiv.style.display = 'block';
358      }
359    }
360    function init()
361    {
362      var iconDir = getRoot()+'images/joust/';
363      IconStore.init(iconDir + 'big/', 18, 22);
364      IconStore.addIcon('JarFile', iconDir + 'jarfile.png', 18, 16);
365      IconStore.addIcon('JarFileError', iconDir + 'jarfileerror.png', 18, 16);
366      IconStore.addIcon('Plugin', iconDir + 'plugin.png', 18, 16);
367      IconStore.addIcon('PluginDisabled', iconDir + 'plugindisabled.png', 18, 16);
368      IconStore.addIcon('PluginWarning', iconDir + 'pluginwarning.png', 18, 16);
369      IconStore.addIcon('Configuration', iconDir + 'item.gif', 18, 16);
370      IconStore.addIcon('ConfigurationWarning', iconDir + 'itemwarning.gif', 18, 16);
371
372      JoustMenu.toggle = function(menuItemIndex)
373      {
374        var menuItem = this.menuItems[menuItemIndex];
375        if (!menuItem) return;
376        // Switch the open/closed status and hide or show the children
377        menuItem.isOpen = !menuItem.isOpen;
378        if (menuItem.isOpen)
379        {
380          this.showChildren(menuItemIndex);
381        }
382        else
383        {
384          this.hideChildren(menuItemIndex);
385        }
386        this.updateIconsAndText(menuItemIndex);
387      }
388     
389      JoustMenu.drawMenuItems = function(firstIndex, indentString)
390      {
391        var menuItem = this.menuItems[firstIndex];
392        while (menuItem)
393        {
394          var html = menuItem.draw(indentString);
395          var padIcon = IconStore.getIcon(menuItem.noOutlineIcon == true ? null : menuItem.nextItemIndex == -1 ? 'iconBlank' : 'iconLine');
396          var padHtml = padIcon == null ? '' : padIcon.getImgTag();
397         
398          var menuDiv = document.getElementById('tree.'+menuItem.externalId);
399          menuDiv.innerHTML = html;
400         
401          if (menuItem.firstChildIndex != -1)
402          {
403            this.drawMenuItems(menuItem.firstChildIndex, indentString+padHtml);
404          }
405          if (!menuItem.isOpen)
406          {
407            this.hideChildren(menuItem.index);
408          }
409          menuItem = this.menuItems[menuItem.nextItemIndex];
410        }
411        return '';
412      }
413
414      JoustMenu.hideChildren = function(menuItemIndex)
415      {
416        var menuItem = this.menuItems[menuItemIndex];
417        if (menuItem)
418        {
419          var firstChildIndex = menuItem.firstChildIndex;
420          var child = this.menuItems[firstChildIndex];
421          while (child)
422          {
423            var e = document.getElementById('row.'+child.externalId);
424            e.style.display = 'none';
425            this.hideChildren(child.index);
426            child = this.menuItems[child.nextItemIndex];
427          }
428        }
429      }
430     
431      JoustMenu.showChildren = function(menuItemIndex)
432      {
433        var menuItem = this.menuItems[menuItemIndex];
434        if (menuItem)
435        {
436          var firstChildIndex = menuItem.firstChildIndex;
437          var child = this.menuItems[firstChildIndex];
438          while (child)
439          {
440            var e = document.getElementById('row.'+child.externalId);
441            e.style.display = Browser.isIE ? 'block' : 'table-row';
442            if (child.isOpen)
443            {
444              this.showChildren(child.index);
445            }
446            child = this.menuItems[child.nextItemIndex];
447          }
448        }
449      }
450      <%=generateJoustTree(plugins)%>
451      JoustMenu.draw('joust');
452    }
453    </script>
454  </base:head>
455  <base:body onload="init()">
456    <form name="autoinstall" action="index.jsp" method="post" onsubmit="return false;">
457    <input type="hidden" name="ID" value="<%=ID%>">
458    <input type="hidden" name="cmd" value="LoadPlugins">
459    <input type="hidden" name="plugindir" value="<%=scanPluginDir ? "1" : "0"%>">
460    <input type="hidden" name="extensionsdir" value="<%=scanExtensionsDir ? "1" : "0"%>">
461   
462    <h3 class="docked"><%=title%> <base:help tabcontrol="plugins" /></h3>
463    <t:tabcontrol id="plugins" contentstyle="<%="height: "+(int)(scale*340)+"px;"%>" 
464      position="bottom">
465      <t:tab id="plugins" title="Available plugins" validate="validatePlugins()" helpid="plugindefinition.autoinstaller">
466        <div align="left">
467          <table border="0" cellspacing="0" cellpadding="0">
468            <tr>
469              <td width="45%"><b>Plugins</b></td>             
470              <td><b>Install</b></td>
471              <td><b>Trusted</b></td>
472              <td><b>Immediate execution</b></td>
473            </tr>
474            <%
475            Iterator<Tree.Entry<Object>> ite = plugins.entryIterator();
476            while (ite.hasNext())
477            {
478              Tree.Entry<Object> entry = ite.next();
479              Object node = entry.getNode();
480              if (node == null) continue;
481              int joustId = System.identityHashCode(entry);
482              String name = node.toString();
483              PluginInfo pluginInfo = null;
484              PluginConfigInfo configInfo = null;
485              java.io.File jarFile = null;
486              Throwable error = null;
487              if (node instanceof PluginInfo)
488              {
489                pluginInfo = (PluginInfo)node;
490                name = pluginInfo.getAbout().getName();
491              }
492              else if (node instanceof PluginConfigInfo)
493              {
494                configInfo = (PluginConfigInfo)node;
495                name = configInfo.getName();
496              }
497              else if (node instanceof java.io.File)
498              {
499                jarFile = (java.io.File)node;
500                name = jarFile.getName();
501              }
502              else if (node instanceof Throwable)
503              {
504                error = (Throwable)node;
505              }
506              %>
507              <tr id="row.<%=joustId%>">
508                <td style="white-space: nowrap;"><div id="tree.<%=joustId%>"><%=name %></div></td>
509                <%
510                if (jarFile != null)
511                {
512                  boolean enableInstall = false;
513                  for (Tree.Entry<Object> child : entry.getChildren())
514                  {
515                    if (child.getNode() instanceof PluginInfo)
516                    {
517                      PluginInfo info = (PluginInfo)child.getNode();
518                      if (!info.isInstalled() || 
519                          !info.inSameJarFile() || 
520                          info.hasDifferentVersion()) 
521                      {
522                        enableInstall = true; 
523                      }
524                    }
525                  }
526                  if (enableInstall)
527                  {
528                    %>
529                    <td><a href="javascript:installAll('<%=jarFile.getAbsolutePath()%>')">Install all</a></td>
530                    <% 
531                  }
532                }
533                if (pluginInfo != null)
534                {
535                  boolean disabled = pluginInfo.isDenied() || 
536                    (pluginInfo.inSameJarFile() && !pluginInfo.hasDifferentVersion());
537                  %>
538                  <td>
539                    <input type="hidden" name="<%=pluginInfo.getClassName()%>:isInstalled" value="<%=pluginInfo.isInstalled()%>">
540                    <input type="hidden" name="<%=pluginInfo.getClassName()%>:inSameJarFile" value="<%=pluginInfo.inSameJarFile()%>">
541                    <input type="hidden" name="<%=pluginInfo.getClassName()%>:hasDifferentVersion" value="<%=pluginInfo.hasDifferentVersion()%>">
542                    <select 
543                      name="<%=pluginInfo.getJarPath()%>:<%=pluginInfo.getClassName()%>"
544                      onchange="pluginOnChange(this)"
545                      style="width:90px"
546                      <%=disabled ? "disabled" : "" %>
547                      >
548                      <%
549                      if (disabled)
550                      {
551                        %>
552                        <option value="" title="Already installed">installed
553                        <%
554                      }
555                      else
556                      {
557                        %>
558                        <option value="" title="Plugin will not be <%=pluginInfo.isInstalled() ? "updated" : "installed"%>" >no
559                        <%
560                      }
561                      if (pluginInfo.hasConfigurations())
562                      {
563                        String titleText = pluginInfo.isInstalled() ? "Plugin will be updated and all configurations will be installed" : 
564                          "Plugin and all configurations will be installed";
565                        %>
566                        <option 
567                          value="plugin" 
568                          title="Only the plugin will be <%=pluginInfo.isInstalled() ? "updated" : "installed"%>" >plugin only
569                        <option 
570                          value="plugin+confs" 
571                          title="<%=titleText%>" >plugin + configurations</option>
572                        <%
573                      }
574                      else
575                      {
576                        %>
577                        <option value="plugin" title="Plugin will be <%=pluginInfo.isInstalled() ? "updated" : "installed"%>">yes
578                        <%
579                      }
580                      %>
581                    </select>
582                    <a onmouseover="javascript:toggleInformation(<%=joustId%>)" 
583                      onmouseout="javascript:toggleInformation(<%=joustId%>)"
584                      ><base:icon image="info.gif"/></a>
585                      <%=getInfoMessage(pluginInfo, joustId) %>
586                  </td>
587                  <%
588                  if (!disabled)
589                  {
590                    %>
591                    <td>
592                      <select name="<%=pluginInfo.getClassName()%>:trusted" 
593                        <%=disabled ? "disabled" : ""%>
594                      >
595                        <option value="0">no
596                        <option value="1">yes
597                      </select>
598                    </td>
599                  <td>
600                    <select name="<%=pluginInfo.getClassName()%>:immediate_execution" 
601                      <%=disabled ? "disabled" : ""%>
602                      >
603                      <option value="0">deny
604                      <option value="1">allow
605                      <%
606                      if (allowImmediateExecution == null)
607                      {
608                        %>
609                        <option value="" selected>auto
610                        <%
611                      }
612                      %>
613                    </select>
614                  </td>
615                  <%
616                }
617              }
618              else if (configInfo != null)
619              {
620                %>
621                <td>
622                  <select 
623                    onchange="configOnChange(this)"
624                    name="<%=configInfo.getPluginClass()%>:config:<%=configInfo.getName()%>">
625                    <option value="0" title="Configuration will not be imported">no</option>
626                    <option value="1" title="Configuration will be imported">yes</option>
627                  </select>
628                </td>
629                <%
630              }
631              %>
632              </tr>
633              <%
634            }
635            %>
636          </table>         
637        </div>
638        <div align="right">
639          &nbsp;<i><base:icon image="joust/plugindisabled.png" /> = plug-in is already installed</i><br>
640          &nbsp;<i><base:icon image="joust/pluginwarning.png" /> = another version is installed</i><br>
641          &nbsp;<i><base:icon image="joust/itemwarning.gif" /> = configuration already exists</i><br>
642        </div>
643      </t:tab>
644    </t:tabcontrol>
645   
646    <table align="center">
647    <tr>
648      <td width="50%"><base:button onclick="saveSettings()" title="Save" /></td>
649      <td width="50%"><base:button onclick="window.close()" title="Cancel" /></td>
650    </tr>
651    </table>
652  </base:body> 
653  </base:page>
654  <% 
655}
656finally
657{
658  if (dc != null) dc.close();
659}
660%>
Note: See TracBrowser for help on using the repository browser.