Changeset 6684


Ignore:
Timestamp:
Jan 14, 2015, 2:29:04 PM (7 years ago)
Author:
Nicklas Nordborg
Message:

Merge changes between 3.4-beta-1 to 3.4.0 to the trunk.

Location:
trunk
Files:
38 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/build.xml

    r6644 r6684  
    486486      <fileset dir="${core.src}" includes="**/*.hbm.xml" />
    487487    </copy>
     488    <copy todir="${build}/hbm"
     489      description="Copy our data class files so xdoclet doesn't parse other code">
     490      <fileset dir="${core.src}" includes="net/sf/basedb/core/data/**/*" />
     491    </copy>
     492   
    488493    <hibernatedoclet
    489494      destdir="${core.build}"
    490495      excludedtags="@version,@author,@todo"
    491496      mergedir="${core.build}"
    492       verbose="${xdoclet.verbose}">
    493       <fileset dir="${core.src}">
     497      verbose="true"
     498      >
     499      <fileset dir="${build}/hbm">
    494500        <include name="net/sf/basedb/core/data/**/*.java"/>
    495501      </fileset>
    496       <hibernate version="2.0"/>
     502      <hibernate version="2.0" />
    497503    </hibernatedoclet>
    498504   
  • trunk/doc/src/docbook/admin/installation.xml

    r6479 r6684  
    565565
    566566          <para>
    567             The second command is important for PostgreSQL users since
    568             the Hibernate database initialisation utility is not able
    569             to create all required indexes. BASE will work without the
    570             indexes but performance is impaired. Running the script as
    571             a MySQL user does not have a negative impact.
     567            The second command is important since
     568            the Hibernate database initialisation utility is not always
     569            able to create all required indexes. In some cases, Hibernate
     570            will also create a new index, even if one already exists.
     571            The command ensures that missing indexes are created and
     572            that duplicates are removed. BASE will work without the
     573            indexes but performance is impaired.
    572574          </para>
    573575
  • trunk/src/clients/web/net/sf/basedb/clients/web/extensions/skin/FixedSkinActionFactory.java

    r6632 r6684  
    2222package net.sf.basedb.clients.web.extensions.skin;
    2323
     24import java.util.Iterator;
     25
    2426import net.sf.basedb.clients.web.extensions.AbstractJspActionFactory;
     27import net.sf.basedb.clients.web.extensions.DynamicActionAttribute;
     28import net.sf.basedb.clients.web.extensions.DynamicActionAttributes;
    2529import net.sf.basedb.clients.web.extensions.ExtensionsControl;
    2630import net.sf.basedb.util.extensions.InvokationContext;
     
    103107 
    104108  static class MySkinAction
    105     implements SkinAction
     109    implements SkinAction, DynamicActionAttributes
    106110  {
    107111    private final FixedSkinActionFactory factory;
     
    136140    }
    137141
     142    @Override
     143    public Iterator<DynamicActionAttribute> getDynamicActionAttributes()
     144    {
     145      return factory.getDynamicActionAttributes();
     146    }
    138147   
    139148  }
  • trunk/src/clients/web/net/sf/basedb/clients/web/taglib/Page.java

    r6632 r6684  
    174174
    175175  /**
     176    Set to TRUE to not use skin on the page.
     177    @since 3.4
     178  */
     179  private boolean noSkin = false;
     180 
     181  /**
    176182    The <!doctype xxx> setting.
    177183  */
     
    253259    return title;
    254260  }
    255 
     261 
     262  /**
     263    Set to TRUE to disable skins.
     264    @since 3.4
     265  */
     266  public void setNoskin(boolean noSkin)
     267  {
     268    this.noSkin = noSkin;
     269  }
     270
     271  public boolean getNoSkin()
     272  {
     273    return noSkin;
     274  }
     275 
    256276  public void setType(String type)
    257277  {
     
    335355  public JspContext getSkinContext()
    336356  {
    337     return skinContext;
     357    return noSkin ? null : skinContext;
    338358  }
    339359 
     
    345365  public List<SkinAction> getSkinActions()
    346366  {
    347     return skinActions;
     367    return noSkin ? null : skinActions;
    348368  }
    349369 
     
    369389    if (type != PAGE_TYPE_INCLUDE)
    370390    {
    371       // Load skin extensions: net.sf.basedb.clients.web.global-skin
    372       skinContext = ExtensionsControl.createContext(sc, pageContext);
    373       skinContext.setAttribute("page-type", getTypeCode());
    374       ExtensionsInvoker<SkinAction> invoker = (ExtensionsInvoker<SkinAction>)ExtensionsControl.useExtensions(skinContext, "net.sf.basedb.clients.web.global-skin");
    375       ActionIterator<SkinAction> it = invoker.iterate();
    376       skinActions = new ArrayList<SkinAction>();
    377       ImageRemapper remapper = ImageRemapperUtil.getNewImageRemapperIfNeeded(pageContext.getServletContext());
    378       while (it.hasNext())
     391      if (!noSkin)
    379392      {
    380         SkinAction skin = it.next();
    381         if (remapper != null) skin.remapImages(remapper);
    382         skinActions.add(skin);
    383         if (favicon == null)
     393        // Load skin extensions: net.sf.basedb.clients.web.global-skin
     394        skinContext = ExtensionsControl.createContext(sc, pageContext);
     395        skinContext.setAttribute("page-type", getTypeCode());
     396        ExtensionsInvoker<SkinAction> invoker = (ExtensionsInvoker<SkinAction>)ExtensionsControl.useExtensions(skinContext, "net.sf.basedb.clients.web.global-skin");
     397        ActionIterator<SkinAction> it = invoker.iterate();
     398        skinActions = new ArrayList<SkinAction>();
     399        ImageRemapper remapper = ImageRemapperUtil.getNewImageRemapperIfNeeded(pageContext.getServletContext());
     400        while (it.hasNext())
    384401        {
    385           String skinIcon = skin.getFavicon();
    386           if (skinIcon != null) favicon = skinIcon;
     402          SkinAction skin = it.next();
     403          if (remapper != null) skin.remapImages(remapper);
     404          skinActions.add(skin);
     405          if (favicon == null)
     406          {
     407            String skinIcon = skin.getFavicon();
     408            if (skinIcon != null) favicon = skinIcon;
     409          }
    387410        }
     411        if (remapper != null) ImageRemapperUtil.setCurrentMapper(remapper);
    388412      }
    389       if (remapper != null) ImageRemapperUtil.setCurrentMapper(remapper);
    390413     
    391414      StringBuilder sb = new StringBuilder();
  • trunk/src/core/net/sf/basedb/core/AnyToAny.java

    r6127 r6684  
    2828import org.hibernate.mapping.Table;
    2929
    30 import net.sf.basedb.core.Transactional.Action;
    3130import net.sf.basedb.core.data.AnyToAnyData;
    3231import net.sf.basedb.core.hibernate.TypeWrapper;
     
    5251public class AnyToAny
    5352  extends BasicItem<AnyToAnyData>
    54   implements Nameable
     53  implements Nameable, Transactional
    5554{
    5655
     
    480479  {
    481480    super.onBeforeCommit(action);
    482     if (action == Action.CREATE)
     481    if (action == Action.CREATE || action == Action.UPDATE && (getToId() == 0 || getFromId() == 0))
    483482    {
    484483      // In case either the to or from items are also new items
  • trunk/src/core/net/sf/basedb/core/DbControl.java

    r6576 r6684  
    4141import net.sf.basedb.util.extensions.manager.ExtensionsManager;
    4242
     43import java.util.HashSet;
    4344import java.util.IdentityHashMap;
    4445import java.util.Iterator;
     
    4950import java.util.HashMap;
    5051import java.util.LinkedHashMap;
     52import java.util.Set;
    5153import java.lang.reflect.Constructor;
    5254
     
    146148 
    147149  /**
     150    Holds random strings that must be unique within a transaction.
     151  */
     152  private Set<String> uniqueRandoms;
     153 
     154  /**
    148155    Create a new object.
    149156  */
     
    169176    itemCache = new IdentityHashMap<BasicData, BasicItem>();
    170177    commitQueue = new LinkedHashMap<BasicItem,Transactional.Action>();
     178    uniqueRandoms = new HashSet<String>();
    171179    isClosed = false;
    172180    isConnected = true;
     
    376384    commitQueue.clear();
    377385    itemCache.clear();
     386    uniqueRandoms.clear();
    378387    if (batchers != null) batchers.clear();
    379388    if (saveIfQueue != null) saveIfQueue.clear();
     
    383392    transactionalActions = null;
    384393    itemCache = null;
     394    uniqueRandoms = null;
    385395    batchers = null;
    386396    isClosed = true;
     
    12111221
    12121222  /**
     1223    Generate a random string value that is unique for the given transaction.
     1224    @since 3.4
     1225  */
     1226  public String uniqueRandom()
     1227  {
     1228    String random = null;
     1229    while (true)
     1230    {
     1231      random = Application.generateRandomId(4);
     1232      if (uniqueRandoms.add(random)) break;
     1233    }
     1234    return random;
     1235  }
     1236 
     1237  /**
    12131238    Add a <code>Batcher</code> to the batcher queue.
    12141239    @param batcher The <code>Batcher</code> to add
  • trunk/src/core/net/sf/basedb/core/HibernateUtil.java

    r6631 r6684  
    4040import net.sf.basedb.core.dbengine.TableInfo.ForeignKeyInfo;
    4141import net.sf.basedb.core.dbengine.TableInfo.IndexInfo;
     42import net.sf.basedb.core.hibernate.DbIndexWork;
    4243import net.sf.basedb.core.hibernate.EntityQueryWrapper;
    4344import net.sf.basedb.core.hibernate.ExecuteUpdateWork;
     
    640641    }
    641642   
    642     if (mode.requireEmptyDatabase())
    643     {
    644       if (!isEmptyDatabase())
    645       {
    646         throw new BaseException("Database already has tables.");
    647       }
     643    boolean emptyDatabase = isEmptyDatabase();
     644    if (mode.requireEmptyDatabase() && !emptyDatabase)
     645    {
     646      throw new BaseException("Database already has tables.");
     647    }
     648    else if (!mode.requireEmptyDatabase() && emptyDatabase)
     649    {
     650      throw new BaseException("Database is empty");
    648651    }
    649652
     
    700703                {
    701704                  isEmpty = false;
    702                   log.error("Table '"+t.getName()+"' already exists; install aborted");
     705                  log.debug("Table '"+t.getName()+"' already exists");
     706                }
     707                else
     708                {
     709                  log.debug("Table '"+t.getName()+"' doesn't exists");
    703710                }
    704711                tables.close();
     
    12521259    try
    12531260    {
    1254       session.close();
     1261      if (session.isOpen()) session.close();
    12551262    }
    12561263    catch(HibernateException ex)
     
    22042211    final boolean dropIndexes, final boolean updateIndexes)
    22052212  {
    2206     final boolean isVerbose = verbose && !silent;
    22072213    Session session = newSession();
    2208    
    2209     try
    2210     {
    2211       HibernateUtil.doWork(session,
    2212         new Work()
    2213         {
    2214           @Override
    2215           public void execute(Connection connection)
    2216             throws SQLException
    2217           {
    2218             Iterator<Table> tables = (Iterator<Table>)cfg.getTableMappings();
    2219             DatabaseMetaData metaData = connection.getMetaData();
    2220             while (tables.hasNext())
    2221             {
    2222               Table table = tables.next();
    2223               if (!silent)
    2224               {
    2225                 System.out.println("=================");
    2226                 System.out.println("Table   : " + table.getName());
    2227               }
    2228               if (isVerbose)
    2229               {
    2230                 System.out.println("Catalog : " + table.getCatalog());
    2231                 System.out.println("Schema  : " + table.getSchema());
    2232               }
    2233          
    2234               if (isVerbose)
    2235               {
    2236                 System.out.println("Database information");
    2237                 System.out.println("--------------------");
    2238               }
    2239              
    2240               TableInfo tiDb = null;
    2241               try
    2242               {
    2243                 tiDb = new TableInfo(table, metaData);
    2244               }
    2245               catch (SQLException ex)
    2246               {
    2247                 throw new BaseException(ex);
    2248               }
    2249          
    2250               if (isVerbose && tiDb != null)
    2251               {
    2252                 // Write all columns
    2253                 for (ColumnInfo ci : tiDb.getColumns())
    2254                 {
    2255                   System.out.println("  Column       : " + ci);
    2256                 }
    2257                
    2258                 // Write primary key
    2259                 System.out.println("  Primary key  : " + tiDb.getPrimaryKey());
    2260              
    2261                 // Write foreign keys
    2262                 for (ForeignKeyInfo fk : tiDb.getForeignKeys())
    2263                 {
    2264                   System.out.println("  Foreign key  : " + fk);
    2265                 }
    2266              
    2267                 // Write indexes and unique constraints
    2268                 for (IndexInfo ii : tiDb.getIndexes())
    2269                 {
    2270                   if (ii.isUnique())
    2271                   {
    2272                     System.out.println("  Unique       : " + ii);
    2273                   }
    2274                   else
    2275                   {
    2276                     System.out.println("  Index        : " + ii);
    2277                   }
    2278                 }
    2279               }
    2280              
    2281               if (isVerbose)
    2282               {
    2283                 System.out.println("Hibernate information");
    2284                 System.out.println("---------------------");
    2285               }
    2286              
    2287               TableInfo tiHib = new TableInfo(table, dialect);
    2288               if (isVerbose)
    2289               {
    2290                 // Write all columns
    2291                 for (ColumnInfo ci : tiHib.getColumns())
    2292                 {
    2293                   System.out.println("  Column       : " + ci);
    2294                 }
    2295                
    2296                 // Write primary key
    2297                 System.out.println("  Primary key  : " + tiHib.getPrimaryKey());
    2298               }
    2299              
    2300               // Write foreign keys
    2301               for (ForeignKeyInfo fk : tiHib.getForeignKeys())
    2302               {
    2303                 if (!silent)
    2304                 {
    2305                   System.out.println("  Foreign key  : " + fk);
    2306                 }
    2307                
    2308                 // Check that an index for the foreign key exists
    2309                 String indexName = tiDb.findIndexName(fk.getName(), fk.getFkColumns());
    2310                 boolean indexExists = indexName != null;
    2311                 String createSql =
    2312                   dbEngine.getCreateIndexSql(table.getCatalog(), table.getSchema(),
    2313                     table.getName(), fk.getName(), fk.getFkColumns(), false);
    2314                 boolean actionCreate = updateIndexes && !indexExists;
    2315                
    2316                 if (!silent)
    2317                 {
    2318                   System.out.println("    Indexed    : " + indexExists + (indexExists ? "(" + indexName + ")" : ""));
    2319                   System.out.println("    INDEX-SQL  : " + createSql);
    2320                   System.out.println("    Actions    : " + (actionCreate ? "CREATE INDEX" : ""));
    2321                 }
    2322                 if (actionCreate)
    2323                 {
    2324                   Statement st = null;
    2325                   try
    2326                   {
    2327                     st = connection.createStatement();
    2328                     if (actionCreate)
    2329                     {
    2330                       log.info("Creating foreign key index: + " + createSql);
    2331                       st.executeUpdate(createSql);
    2332                     }
    2333                     connection.commit();
    2334                     st.close();
    2335                     st = null;
    2336                   }
    2337                   catch (SQLException ex)
    2338                   {
    2339                     log.error("Exception", ex);
    2340                     throw new BaseException(ex);
    2341                   }
    2342                   finally
    2343                   {
    2344                     if (st != null)
    2345                     {
    2346                       try
    2347                       {
    2348                         st.close();
    2349                       }
    2350                       catch (Throwable t)
    2351                       {
    2352                         log.error("Exception", t);
    2353                       }
    2354                     }
    2355                   }
    2356                 }
    2357               }
    2358          
    2359               // Write indexes and unique constraints
    2360               for (IndexInfo ii : tiHib.getIndexes())
    2361               {
    2362                 if (!silent)
    2363                 {
    2364                   if (ii.isUnique())
    2365                   {
    2366                     System.out.println("  Unique       : " + ii);
    2367                   }
    2368                   else
    2369                   {
    2370                     System.out.println("  Index        : " + ii);
    2371                   }
    2372                 }
    2373                  
    2374                 String dbName = tiDb.findIndexName(ii.getName(), ii.getColumns());
    2375                 boolean exists = dbName != null;
    2376                 boolean safeToDrop = exists && tiDb.safeToDrop(ii);
    2377          
    2378                 String dropSql = exists ?
    2379                   dbEngine.getDropIndexSql(table.getCatalog(), table.getSchema(),
    2380                     table.getName(), dbName, ii.isUnique()) : "";
    2381                 String createSql =
    2382                   dbEngine.getCreateIndexSql(table.getCatalog(), table.getSchema(),
    2383                     table.getName(), table.getName() + "_" + ii.getName(),
    2384                   ii.getColumns(), ii.isUnique());
    2385                 boolean actionDrop = dropIndexes && exists && safeToDrop;
    2386                 boolean actionCreate = updateIndexes && (actionDrop || !exists);
    2387                
    2388                 if (!silent)
    2389                 {
    2390                   System.out.println("    Exists     : " + exists + (exists ? "(" + dbName + ")" : ""));
    2391                   System.out.println("    Safe drop  : " + safeToDrop);
    2392                   System.out.println("    DROP-SQL   : " + dropSql);
    2393                   System.out.println("    CREATE-SQL : " + createSql);
    2394                   System.out.println("    Actions    : " + (actionDrop ? "DROP " : "") +
    2395                     (actionCreate ? "CREATE" : ""));
    2396                 }
    2397                 if (actionDrop || actionCreate)
    2398                 {
    2399                   Statement st = null;
    2400                   try
    2401                   {
    2402                     st = connection.createStatement();
    2403                     if (actionDrop)
    2404                     {
    2405                       log.info("Dropping index: + " + dropSql);
    2406                       st.executeUpdate(dropSql);
    2407                     }
    2408                     if (actionCreate)
    2409                     {
    2410                       log.info("Creating index: + " + createSql);
    2411                       st.executeUpdate(createSql);
    2412                     }
    2413                     connection.commit();
    2414                     st.close();
    2415                     st = null;
    2416                   }
    2417                   catch (SQLException ex)
    2418                   {
    2419                     log.error("Exception", ex);
    2420                     throw new BaseException(ex);
    2421                   }
    2422                   finally
    2423                   {
    2424                     if (st != null)
    2425                     {
    2426                       try
    2427                       {
    2428                         st.close();
    2429                       }
    2430                       catch (Throwable t)
    2431                       {
    2432                         log.error("Exception", t);
    2433                       }
    2434                     }
    2435                   }
    2436                 }
    2437                
    2438               }
    2439              
    2440               if (!silent)
    2441               {
    2442                 System.out.println("=================");
    2443                 System.out.println("");
    2444               }
    2445             }
    2446            
    2447           }
    2448        
    2449         }
    2450       );
     2214    try
     2215    {
     2216      HibernateUtil.doWork(session, new DbIndexWork(cfg, dialect, dbEngine, verbose, silent, dropIndexes, updateIndexes));
    24512217    }
    24522218    catch (SQLException ex)
    2453     {
    2454      
    2455     }
    2456    
     2219    {}
    24572220  }
    24582221
  • trunk/src/core/net/sf/basedb/core/ItemContext.java

    r6336 r6684  
    17201720      // propertyDef is JEP expression
    17211721      Expression e = Jep.formulaToExpression(propertyDef.substring(1), ch, rawCh, raw, rep, mrep);
    1722       s = Selects.expression(e, "jep" + System.identityHashCode(e));
     1722      s = Selects.expression(e, "jep" + dc.uniqueRandom());
    17231723    }
    17241724    else
  • trunk/src/core/net/sf/basedb/core/PropertyFilter.java

    r6214 r6684  
    515515            if (obj != null)
    516516            {
    517               String parameterName = "p" + System.identityHashCode(obj);
     517              String parameterName = "p" + dc.uniqueRandom();
    518518              Type theValueType = obj instanceof Double ? Type.DOUBLE : getValueType();
    519519              if (theValueType == Type.TIMESTAMP) theValueType = Type.DATE;
     
    526526        else
    527527        {
    528           String parameterName = "p" + System.identityHashCode(this);
     528          String parameterName = "p" + dc.uniqueRandom();
    529529          Expression parameter = null;
    530530          if (getValue() != null)
     
    605605    else
    606606    {
    607       String parameterName = "p" + System.identityHashCode(this);
     607      String parameterName = "p" + dc.uniqueRandom();
    608608      Expression parameter = null;
    609609      if (getValue() != null && !operator.isListOperator())
     
    632632            if (obj != null)
    633633            {
    634               parameterName = "p" + System.identityHashCode(obj);
     634              parameterName = "p" + dc.uniqueRandom();
    635635              Type theValueType = obj instanceof Double ? Type.DOUBLE : getValueType();
    636636              Expression e = Expressions.parameter(parameterName, obj, theValueType);
     
    674674        String entityCollection = m.group(1);
    675675        String collectionFilter = m.group(2);
     676        boolean rewriteNullFilter = false;
     677        if (collectionFilter.startsWith("%"))
     678        {
     679          collectionFilter = collectionFilter.substring(1);
     680          rewriteNullFilter = true;
     681        }
    676682       
    677683        /*
     
    732738        }
    733739       
     740        boolean notContains = subfilterOperator != operator;
     741        Operator actualOperator = subfilterOperator;
     742        String actualValue = getValue();
     743        if (rewriteNullFilter && actualValue == null && subfilterOperator == Operator.EQ)
     744        {
     745          // =ANY(... WHERE <property> IS NULL) is rewritten as
     746          // <>ALL(... WHERE <property> LIKE '%')
     747          actualOperator = Operator.LIKE;
     748          actualValue = "%";
     749          notContains = !notContains;
     750        }
     751       
    734752        // Restrict the subquery
    735753        PropertyFilter pp = new PropertyFilter("$" + thisAlias + "." + collectionFilter,
    736             subfilterOperator, getValue(), getValueType());
     754            actualOperator, actualValue, getValueType());
    737755        subquery.restrict(pp.getRestriction(dc, query));
    738756       
    739757        // Create the main restriction
    740         if (subfilterOperator != operator)
     758        if (notContains)
    741759        {
    742760          // "not contains": root-entity <> ALL(subquery)
     
    807825            if (obj != null)
    808826            {
    809               parameterName = "p" + System.identityHashCode(obj);
     827              parameterName = "p" + dc.uniqueRandom();
    810828              Type theValueType = obj instanceof Double ? Type.DOUBLE : getValueType();
    811829              if (theValueType == Type.TIMESTAMP) theValueType = Type.DATE;
     
    859877      propertyExpression = ItemContext.getDynamicExpression(dc, property);
    860878    }
    861     String parameterName = "p" + System.identityHashCode(this);
     879    String parameterName = "p" + dc.uniqueRandom();
    862880   
    863881    String value = getValue();
     
    900918          if (obj != null)
    901919          {
    902             parameterName = "p" + System.identityHashCode(obj);
     920            parameterName = "p" + dc.uniqueRandom();
    903921            e = Expressions.parameter(parameterName, obj);
    904922          }
  • trunk/src/core/net/sf/basedb/core/RawDataTypes.java

    r6473 r6684  
    161161  {
    162162    List<String> files = Application.getRawDataTypeFiles();
     163    Set<String> usedNames = new HashSet<String>();
    163164    try
    164165    {
     
    166167      {
    167168        Document dom = XmlUtil2.getValidatedXml(RawDataTypes.class.getResource(xmlFile), dtdFile);
    168         loadRawDataTypes(dom, xmlFile);
     169        loadRawDataTypes(usedNames, dom, xmlFile);
    169170        log.info("Loaded raw data types from file: " + xmlFile);
    170171      }
     
    334335    {@link #rawDataTypes} map.
    335336  */
    336   private static void loadRawDataTypes(Document dom, String xmlFile)
     337  private static void loadRawDataTypes(Set<String> usedNames, Document dom, String xmlFile)
    337338  {
    338339    List<Element> rawDataTypeTags = dom.getRootElement().getChildren("raw-data-type");
    339340    DbEngine engine = HibernateUtil.getDbEngine();
    340     Set<String> usedNames = new HashSet<String>();
    341341    for (Element el : rawDataTypeTags)
    342342    {
  • trunk/src/core/net/sf/basedb/core/ServiceSessionControl.java

    r6631 r6684  
    3131import net.sf.basedb.core.data.UserData;
    3232import net.sf.basedb.core.dbengine.DbEngine;
     33import net.sf.basedb.core.hibernate.DbIndexWork;
    3334import net.sf.basedb.core.hibernate.GetCurrentCatalogWork;
    3435import net.sf.basedb.core.hibernate.SchemaExistsWork;
     
    4445import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
    4546import org.hibernate.cfg.Configuration;
     47import org.hibernate.dialect.Dialect;
    4648import org.hibernate.service.ServiceRegistry;
    4749
     
    138140      // but MySQL don't have schemas so actual catalog is a combined of both
    139141      DbEngine dbEngine = HibernateUtil.getDbEngine();
     142      Dialect dialect = HibernateUtil.getDialect();
    140143      String actualCatalog = dbEngine.getCatalogName(catalog, schema);
    141144      String actualSchema = dbEngine.getSchemaName(catalog, schema);
    142145
    143       if (log.isDebugEnabled()) log.debug("Actual catalog/schema: " + actualCatalog + "/" + actualSchema);
    144      
     146      if (log.isDebugEnabled()) log.debug("Actual catalog/schema: " + actualCatalog + "/" + actualSchema);   
    145147      if (actualCatalog != null)
    146148      {
     
    188190      if (mode != null)
    189191      {
     192        // Generates tables and most other things
    190193        SchemaGenerator schemaGenerator =
    191           new SchemaGenerator(cfg, HibernateUtil.getDialect(), dbEngine, mode, null);
     194          new SchemaGenerator(cfg, dialect, dbEngine, mode, null);
    192195        session.doWork(schemaGenerator);
     196        // Generates missing indexes
     197        DbIndexWork indexGenerator = new DbIndexWork(cfg, dialect, dbEngine, false, true, false, true);
     198        session.doWork(indexGenerator);
     199        // Update schema version in BASE
    193200        if (config.getAppId() != null)
    194201        {
     
    196203        }
    197204        HibernateUtil.commit(tx);
     205        tx = null;
    198206      }
    199207     
     
    228236  /**
    229237    Create a new Hibernate session for the given session factory that
    230     is piggy-backed on the given DbControl transaction.
     238    is piggy-backed on the given DbControl transaction.
     239   
     240    Note that the life-cycle of the returned session is managed by the
     241    DbControl. There is no need to flush or close the session since this
     242    is done automatically and may cause exceptions if done when not needed.
    231243   
    232244    @param A session builder (eg. SessionFactory.withOptions())
  • trunk/src/core/net/sf/basedb/core/data/ExtractData.java

    r6279 r6684  
    7575  }
    7676 
     77  private Set<DerivedBioAssayData> derivedBioAssays;
     78  /**
     79    This is the inverse end.
     80    @see DerivedBioAssayData#getExtract()
     81    @since 3.4
     82    @hibernate.set lazy="true" inverse="true"
     83    @hibernate.collection-key column="`extract_id`"
     84    @hibernate.collection-one-to-many class="net.sf.basedb.core.data.DerivedBioAssayData"
     85  */
     86  Set<DerivedBioAssayData> getDerivedBioAssays()
     87  {
     88    return derivedBioAssays;
     89  }
     90  void setDerivedBioAssays(Set<DerivedBioAssayData> derivedBioAssays)
     91  {
     92    this.derivedBioAssays = derivedBioAssays;
     93  }
     94
    7795}
  • trunk/src/core/net/sf/basedb/core/dbengine/MySQLEngine.java

    r6630 r6684  
    2727import java.util.regex.Pattern;
    2828
     29import net.sf.basedb.core.hibernate.SchemaGenerator;
     30
     31import org.hibernate.dialect.Dialect;
    2932import org.hibernate.mapping.PersistentClass;
    3033
     
    211214
    212215  /**
     216    Fix "alter table ... drop constraint ..." statements that are generated
     217    incorrectly by Hibernate.
     218    @since 3.4
     219  */
     220  @Override
     221  public String inspectSchemaGenerationSQL(String sql, Dialect dialect,
     222      SchemaGenerator.Mode mode)
     223  {
     224    sql = super.inspectSchemaGenerationSQL(sql, dialect, mode);
     225    if (sql != null && sql.startsWith("alter table") && sql.contains("drop constraint"))
     226    {
     227      sql = sql.replace("drop constraint", "drop index");
     228    }
     229    return sql;
     230  }
     231
     232 
     233  /**
    213234    Return true.
    214235  */
  • trunk/src/core/net/sf/basedb/core/dbengine/PostgresDbEngine.java

    r6630 r6684  
    7777    Generate <code>ALTER TABLE &lt;schema&gt;.&lt;table&gt; ADD CONSTRAINT &lt;name&gt;
    7878    UNIQUE (&lt;columns&gt)</code> for a unique index,
    79     <code>CREATE INDEX &lt;schema&gt;.&lt;name&gt; ON &lt;schema&gt;.&lt;table&gt; (&lt;columns&gt;)</code>
     79    <code>CREATE INDEX &lt;name&gt; ON &lt;schema&gt;.&lt;table&gt; (&lt;columns&gt;)</code>
    8080    for other indexes.
    8181    The catalog parameter is not supported.
     
    9898    {
    9999      sql.append("CREATE INDEX ");
    100       if (schema != null) sql.append(getQuotedName(schema)).append(".");
    101100      sql.append(getQuotedName(name)).append(" ON ");
    102101      if (schema != null) sql.append(getQuotedName(schema)).append(".");
  • trunk/src/core/net/sf/basedb/core/dbengine/TableInfo.java

    r6127 r6684  
    2828import java.sql.Statement;
    2929import java.sql.Types;
     30import java.util.ArrayList;
    3031import java.util.Arrays;
    3132import java.util.Collections;
     
    115116  }
    116117 
     118 
    117119  /**
    118120    Create table info by reading JDBC metadata from the current database
     
    123125  */
    124126  public TableInfo(Table table, DatabaseMetaData metaData)
     127      throws SQLException
     128  {
     129    this(table, metaData, null, null);
     130  }
     131
     132  /**
     133    Create table info by reading JDBC metadata from the current database
     134   
     135    @param table The Hibernate table object
     136    @param metaData The JDBC metadata connected to the current database
     137    @param defaultCatalog Catalog to use if the table doesn't specify a catalog
     138    @param defaultSchema Schema to use if the table doesn't specify a catalog
     139    @throws SQLException If there is an error
     140    @since 3.4
     141  */
     142  public TableInfo(Table table, DatabaseMetaData metaData, String defaultCatalog, String defaultSchema)
    125143    throws SQLException
    126144  {
    127145    this(table);
    128146   
    129     ResultSet tables = metaData.getTables(table.getCatalog(), table.getSchema(), table.getName(), null);
     147    String catalog = table.getCatalog();
     148    if (catalog == null) catalog = defaultCatalog;
     149    String schema = table.getSchema();
     150    if (schema == null) schema = defaultSchema;
     151   
     152    ResultSet tables = metaData.getTables(catalog, schema, table.getName(), null);
    130153    existsInDb = tables.next();
    131154    tables.close();
    132    
    133155    if (!existsInDb) return;
    134156   
    135157    // Load column information
    136     ResultSet sqlColumns = metaData.getColumns(table.getCatalog(), table.getSchema(), table.getName(), "%");
     158    ResultSet sqlColumns = metaData.getColumns(catalog, schema, table.getName(), "%");
    137159    while (sqlColumns.next())
    138160    {
     
    147169   
    148170    // Load primary key information
    149     ResultSet sqlPK = metaData.getPrimaryKeys(table.getCatalog(), table.getSchema(), table.getName());
     171    ResultSet sqlPK = metaData.getPrimaryKeys(catalog, schema, table.getName());
    150172    Set<String> pkColumns = new LinkedHashSet<String>();
    151173    String pkName = null;
     
    162184   
    163185    // Load foreign keys
    164     ResultSet sqlFK = metaData.getImportedKeys(table.getCatalog(), table.getSchema(), table.getName());
     186    ResultSet sqlFK = metaData.getImportedKeys(catalog, schema, table.getName());
    165187    Map<String, ForeignKeyInfo> fkInfo = new HashMap<String, ForeignKeyInfo>();
    166188    while (sqlFK.next())
     
    184206   
    185207    // Load indexes
    186     ResultSet sqlIndexes = metaData.getIndexInfo(table.getCatalog(), table.getSchema(), table.getName(), false, true);
     208    ResultSet sqlIndexes = metaData.getIndexInfo(catalog, schema, table.getName(), false, true);
    187209    Map<String, IndexInfo> indexInfo = new HashMap<String, IndexInfo>();
    188210    while (sqlIndexes.next())
     
    191213      String column = makeSafe(sqlIndexes.getString("COLUMN_NAME"));
    192214      boolean isUnique = !sqlIndexes.getBoolean("NON_UNIQUE");
    193      
    194215      IndexInfo ii = indexInfo.get(indexName);
    195216      if (ii == null)
     
    441462    }
    442463    return null;
     464  }
     465 
     466  /**
     467    Find all indexes with the given set of columns. Used for
     468    getting rid of duplicates.
     469    @param columns A set containing the column names that should be present in
     470      the index
     471    @return A list with the index information or an empty list of no index is found
     472    @since 3.4
     473  */
     474  public List<IndexInfo> findAll(Set<String> columns)
     475  {
     476    List<IndexInfo> all = new ArrayList<IndexInfo>();
     477    for (IndexInfo iiInfo : indexes)
     478    {
     479      if (columns.equals(iiInfo.getColumns())) all.add(iiInfo);
     480    }
     481    return all;
    443482  }
    444483
  • trunk/src/core/net/sf/basedb/core/hibernate/SchemaGenerator.java

    r6468 r6684  
    120120      int numDone = 0;
    121121      int interval = Math.max(1, numStatements / 30);
     122     
    122123      for (SchemaUpdateScript script : allSql)
    123124      {
     
    131132          }
    132133          log.debug("Executing: " + actualSql);
    133           stmt.executeUpdate(actualSql);
    134           //System.out.println(actualSql);
     134          try
     135          {
     136            stmt.executeUpdate(actualSql);
     137          }
     138          catch (SQLException | RuntimeException ex)
     139          {
     140            if (script.isQuiet())
     141            {
     142              log.info("Ignoring quiet SQL: "+ actualSql, ex);
     143            }
     144            else
     145            {
     146              throw ex;
     147            }
     148          }
    135149          if (progress != null)
    136150          {
     
    153167      }
    154168    }
    155     catch (SQLException ex)
     169    catch (SQLException | RuntimeException ex)
    156170    {
    157171      log.error("Schema update failed", ex);
  • trunk/src/core/net/sf/basedb/core/signal/AbstractSignalReceiver.java

    r6444 r6684  
    2828import java.util.HashMap;
    2929import java.util.Map;
     30import java.util.WeakHashMap;
     31
     32import net.sf.basedb.core.Application;
    3033
    3134/**
     
    7679  */
    7780  private Map<String, SignalHandler> handlers;
     81  private Map<SignalHandler, String> handlerIds;
    7882  private String receiverId;
    7983  private Thread notifyThread;
     
    98102  {
    99103    handlers = Collections.synchronizedMap(new HashMap<String, SignalHandler>());
     104    handlerIds = new WeakHashMap<SignalHandler, String>();
    100105    this.receiverId = receiverId;
    101106    logger.info("Initializing signal receiver: id=" + receiverId);
     
    165170  {
    166171    if (notifyThread != null) throw new SignalException("Signal receiver is shutting down.");
     172    String localId = getLocalSignalHandlerId(handler);
    167173    String globalId = getGlobalSignalId(handler);
    168     String localId = getLocalSignalHandlerId(handler);
    169174    if (handlers != null)
    170175    {
    171       if (handlers.containsKey(localId))
    172       {
    173         throw new SignalException("A handler with ID '" + localId + "' is already registered: "
    174           + handlers.get(localId));
    175       }
    176       handlers.put(localId, handler);
     176      synchronized (handlers)
     177      {
     178        if (handlers.containsKey(localId))
     179        {
     180          throw new SignalException("A handler with ID '" + localId + "' is already registered: "
     181            + handlers.get(localId));
     182        }
     183        handlers.put(localId, handler);
     184      }
    177185    }
    178186
     
    180188      "; global id=" + globalId + "; local id=" + localId);
    181189    logger.debug("Current number of registered signal handlers: " +
    182       (handlers == null ? 0 : handlers.size()));
     190      (handlers == null ? "0/0" : handlers.size()+"/"+handlerIds.size()));
    183191    return globalId;
    184192  }
     
    196204    if (handlers != null)
    197205    {
    198       handlers.remove(localId);
     206      synchronized (handlers)
     207      {
     208        handlers.remove(localId);
     209        handlerIds.remove(handler);
     210      }
    199211      // If called from the close() method() this is waiting for
    200212      if (notifyThread != null && handlers.size() == 0)
     
    205217    }
    206218    logger.debug("Current number of registered signal handlers: " +
    207       (handlers == null ? 0 : handlers.size()));
     219      (handlers == null ? "0/0" : handlers.size()+"/"+handlerIds.size()));
    208220  }
    209221 
     
    274286  /**
    275287    Get the local signal handler id of the given signal handler.
    276     This implementation simply return the system hashcode for the
    277     handler. The returned ID must be unique among the registered
    278     signal handlers.
     288    This implementation generates a unique ID for the handler.
    279289    @param handler The handler to get the id for
    280290    @return The local handler id
     
    282292  protected String getLocalSignalHandlerId(SignalHandler handler)
    283293  {
    284     return String.valueOf(System.identityHashCode(handler));
     294    if (handlerIds == null) return String.valueOf(System.identityHashCode(handler));
     295    String id = handlerIds.get(handler);
     296    if (id == null)
     297    {
     298      synchronized (handlers)
     299      {
     300        while (true)
     301        {
     302          id = Application.generateRandomId(4);
     303          if (!handlers.containsKey(id)) break;
     304        }
     305        handlerIds.put(handler, id);
     306      }
     307    }
     308    return id;
    285309  }
    286310 
  • trunk/src/core/net/sf/basedb/util/timer/ThreadTimerTask.java

    r6127 r6684  
    8585          public void run()
    8686          {
    87             task.run();
    88             isExecuting = false;
     87            try
     88            {
     89              task.run();
     90            }
     91            finally
     92            {
     93              isExecuting = false;
     94            }
    8995          }
    9096        }
  • trunk/src/test/TestAnyToAny.java

    r6100 r6684  
    7171    test_exists(sampleId, "third", false);
    7272
     73    // Test relinking to a new item in a single transaction
     74    int sampleId2 = test_relink(id);
     75   
    7376    // Standard test: Delete
    7477    if (TestUtil.waitBeforeDelete()) TestUtil.waitForEnter();
     
    8285   
    8386    TestSample.test_delete(sampleId);
     87    TestSample.test_delete(sampleId2);
    8488    TestFile.test_delete(fileId1);
    8589    TestFile.test_delete(fileId2);
     
    121125  }
    122126
     127  static int test_relink(int id)
     128  {
     129    if (id == 0) return 0;
     130    int sampleId = 0;
     131    DbControl dc = null;
     132    try
     133    {
     134      dc = TestUtil.getDbControl();
     135      Sample s = Sample.getNew(dc);
     136      dc.saveItem(s);
     137
     138      AnyToAny a = AnyToAny.getById(dc, id);
     139      a.setTo(s);
     140      a.setDescription("Relinked "+new Date());
     141      dc.commit();
     142     
     143      sampleId = s.getId();
     144      dc = TestUtil.getDbControl();
     145      dc.reattachItem(a, false);
     146      write_item(0, a);
     147      if (a.getToId() != sampleId)
     148      {
     149        throw new BaseException("Relink failed: " + a.getToId() + " != " + sampleId);
     150      }
     151      write("--Relink any-to-any OK");
     152    }
     153    catch (Throwable ex)
     154    {
     155      write("--Relink any-to-any FAILED");
     156      ex.printStackTrace();
     157      ok = false;
     158    }
     159    finally
     160    {
     161      if (dc != null) dc.close();
     162    }
     163    return sampleId;   
     164  }
     165 
    123166  static void test_load(int id)
    124167  {
     
    185228  {
    186229    if (!TestUtil.getSilent()) System.out.println(i+":\t"+a.getId()+"\t"+a.getName()+"\t"+
    187       a.getDescription()+"\t"+a.getFrom()+"\t"+a.getTo());
     230      a.getDescription()+"\t"+a.getFromType()+"["+a.getFromId()+"]\t"+a.getToType()+"["+a.getToId()+"]");
    188231  }
    189232  static void write(String message)
  • trunk/src/test/TestJarClassLoader.java

    r6640 r6684  
    4343    write("++Testing Jar class loader");
    4444   
    45     test_load("JarPlugin.jar", "JarPlugin", false, true);
     45    test_load("JarPlugin.jar", "JarPlugin", false, true, false);
    4646    test_resource("JarPlugin.jar", "META-INF/MANIFEST.MF", false, true);
    4747   
    4848    // Test parent delegation
    49     test_load("JarPlugin.jar", "affymetrix.calvin.exception.CalvinException", false, true);
     49    test_load("JarPlugin.jar", "affymetrix.calvin.exception.CalvinException", false, true, false);
    5050    test_resource("JarPlugin.jar", "org/hibernate/hibernate-configuration-3.0.dtd", false, false);
    51     test_load("JarPlugin.jar", "affymetrix.calvin.exception.CalvinException", true, false);
     51    test_load("JarPlugin.jar", "affymetrix.calvin.exception.CalvinException", true, false, true);
    5252    test_resource("JarPlugin.jar", "org/hibernate/hibernate-configuration-3.0.dtd", true, false);
    5353   
     
    5757
    5858  static void test_load(String jarPath, String className,
    59       boolean delegateFirst, boolean expectLoadedByJarClassLoader)
     59      boolean delegateFirst, boolean expectLoadedByJarClassLoader, boolean useNewInstance)
    6060  {
    6161    try
    6262    {
    63       JarClassLoader cl = (JarClassLoader)JarClassLoader.getInstance(jarPath);
     63      JarClassLoader cl = useNewInstance ?
     64        (JarClassLoader)JarClassLoader.newInstance(jarPath) :
     65        (JarClassLoader)JarClassLoader.getInstance(jarPath);
    6466      cl.setDelegateFirst(delegateFirst);
    6567      Class c = cl.loadClass(className);
  • trunk/www/WEB-INF/base.tld

    r6655 r6684  
    6262      <rtexprvalue>true</rtexprvalue>
    6363    </attribute>
     64    <attribute>
     65      <name>noskin</name>
     66      <rtexprvalue>true</rtexprvalue>
     67    </attribute>
    6468  </tag>
    6569
  • trunk/www/admin/annotationtypes/edit_annotationtype.jsp

    r6608 r6684  
    861861                data-initial-items="[<%=HTML.encodeTags(jsonUsableUnits.toJSONString()) %>]"
    862862                data-remove-to="allUnits"
    863                 size="10" multiple style="width: 100%;"
     863                size="10" multiple style="width: calc(100% - 10px);"
    864864                title="If no unit is selected, all units can be used"
    865865              >
     
    886886            </td>
    887887            <td style="width: 50%;">
    888               <select name="allUnits" id="allUnits" size="10" multiple style="width: 100%;">
     888              <select name="allUnits" id="allUnits" size="10" multiple style="width: calc(100% - 10px);">
    889889              </select>
    890890            </td>
  • trunk/www/admin/extensions/tree.jsp

    r6409 r6684  
    4949<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
    5050<%!
    51 JSONObject newJoustExtensionPoint(JSONObject jsonParent, ExtensionsControl ec, ExtensionPoint ep, ExtensionsFile ef)
     51JSONObject newJoustExtensionPoint(DbControl dc, JSONObject jsonParent, ExtensionsControl ec, ExtensionPoint ep, ExtensionsFile ef)
    5252{
    5353  String id = ep.getId();
     
    5959    icon = "ExtensionPointError";
    6060  }
    61   JSONObject json = newJoustEntry(jsonParent, icon, HTML.encodeTags(name), id);
     61  JSONObject json = newJoustEntry(dc, jsonParent, icon, HTML.encodeTags(name), id);
    6262  json.put("type", "extension-point");
    6363  return json;
    6464}
    6565
    66 JSONObject newJoustExtension(JSONObject jsonParent, ExtensionsControl ec, Extension ext, ExtensionsFile ef, boolean inGroup, boolean showFile)
     66JSONObject newJoustExtension(DbControl dc, JSONObject jsonParent, ExtensionsControl ec, Extension ext, ExtensionsFile ef, boolean inGroup, boolean showFile)
    6767{
    6868  String id = ext.getId();
     
    8888  }
    8989 
    90   JSONObject json = newJoustEntry(jsonParent, icon, name, id);
     90  JSONObject json = newJoustEntry(dc, jsonParent, icon, name, id);
    9191  json.put("type", "extension");
    9292  return json;
    9393}
    9494
    95 JSONObject newJoustFile(JSONObject jsonParent, ExtensionsFile ef, ExtensionsControl ec)
     95JSONObject newJoustFile(DbControl dc, JSONObject jsonParent, ExtensionsFile ef, ExtensionsControl ec)
    9696{
    9797  String efName = ef.getName();
     
    107107  if (ef.checkModified()) icon += "Modified";
    108108 
    109   JSONObject json = newJoustEntry(jsonParent, icon, HTML.encodeTags(efName), efName);
     109  JSONObject json = newJoustEntry(dc, jsonParent, icon, HTML.encodeTags(efName), efName);
    110110  json.put("id", efName);
    111111  json.put("type", "file");
     
    114114}
    115115
    116 JSONObject newJoustExtensionGroup(JSONObject jsonParent, ExtensionsControl ec, Extension ext, String groupId)
     116JSONObject newJoustExtensionGroup(DbControl dc, JSONObject jsonParent, ExtensionsControl ec, Extension ext, String groupId)
    117117{
    118118  String id = ext.getId();
     
    120120  String name = about == null || about.getName() == null ? id : about.getName();
    121121  String icon = "Folder";
    122   JSONObject json = newJoustEntry(jsonParent, icon, HTML.encodeTags(name), groupId);
     122  JSONObject json = newJoustEntry(dc, jsonParent, icon, HTML.encodeTags(name), groupId);
    123123  json.put("type", "group");
    124124  return json;
    125125}
    126126
    127 JSONObject newJoustPlugin(JSONObject jsonParent, ExtensionsControl ex, PluginInfo info, ExtensionsFile ef)
     127JSONObject newJoustPlugin(DbControl dc, JSONObject jsonParent, ExtensionsControl ex, PluginInfo info, ExtensionsFile ef)
    128128{
    129129  String id = info.getClassName();
     
    140140  }
    141141 
    142   JSONObject json = newJoustEntry(jsonParent, icon, name, id);
     142  JSONObject json = newJoustEntry(dc, jsonParent, icon, name, id);
    143143  json.put("type", "plugin");
    144144  json.put("className", info.getClassName());
     
    146146}
    147147
    148 JSONObject newJoustEntry(JSONObject jsonParent, String icon, String text, String id)
     148JSONObject newJoustEntry(DbControl dc, JSONObject jsonParent, String icon, String text, String id)
    149149{
    150150  JSONObject jsonJoust = new JSONObject();
    151151  jsonJoust.put("icon", icon);
    152152  jsonJoust.put("text", text);
    153   jsonJoust.put("id", "joust-"+System.identityHashCode(jsonJoust));
     153  jsonJoust.put("id", "joust-"+dc.uniqueRandom());
    154154  jsonJoust.put("externalId", id);
    155155  if (jsonParent != null)
     
    172172DbControl dc = null;
    173173
    174 // Build the Joust menu tree
    175 JSONArray jsonJoust = new JSONArray();
    176 
    177 // Two ROOT items:
    178 JSONObject jsonByExtPoint = newJoustEntry(null, "Root", "By extension point", "root.by-extension-point");
    179 jsonByExtPoint.put("isOpen", 1);
    180 JSONObject jsonByFile = newJoustEntry(null, "Root", "By file", "root.by-file");
    181 jsonByFile.put("isOpen", 1);
    182 
    183 // Group some extension points inside sub-folders
    184 JSONObject jsonToolbars = newJoustEntry(jsonByExtPoint, "Folder", "Toolbars", "by-extension-point.toolbars");
    185 JSONObject jsonEditDialogs = newJoustEntry(jsonByExtPoint, "Folder", "Edit dialogs", "by-extension-point.edit-dialogs");
    186 JSONObject jsonListColumns = newJoustEntry(jsonByExtPoint, "Folder", "List columns", "by-extension-point.list-columns");
    187 
    188 jsonJoust.add(jsonByExtPoint);
    189 jsonJoust.add(jsonByFile);
    190 
    191 ExtensionsControl ec = ExtensionsControl.get(dc);
    192 List<ExtensionPoint<?>> extensionPoints = ec.getExtensionPoints();
    193 Collections.sort(extensionPoints, Registry.EXTENSIONPOINT_COMPARATOR);
    194 for (ExtensionPoint ep : extensionPoints)
    195 {
    196   String id = ep.getId();
    197   JSONObject jsonParent = jsonByExtPoint;
    198   if (id.startsWith("net.sf.basedb.clients.web.toolbar.")) jsonParent = jsonToolbars;
    199   if (id.startsWith("net.sf.basedb.clients.web.tabcontrol.edit.")) jsonParent = jsonEditDialogs;
    200   if (id.startsWith("net.sf.basedb.clients.web.onsave.")) jsonParent = jsonEditDialogs;
    201   if (id.startsWith("net.sf.basedb.clients.web.listcolumn.")) jsonParent = jsonListColumns;
    202  
    203   JSONObject jsonEp = newJoustExtensionPoint(jsonParent, ec, ep, ec.getFileByObjectKey(new ExtensionPointKey(ep)));
    204 
    205   List<Extension<?>> extensions = ec.getExtensions(ep.getId());
    206   Collections.sort(extensions, Registry.EXTENSION_COMPARATOR);
    207   for (Extension ext : extensions)
    208   {
    209     newJoustExtension(jsonEp, ec, ext, ec.getFileByObjectKey(new ExtensionKey(ext)), false, true);
    210   }
    211 }
    212 
    213 for (ExtensionsFile ef : ec.getFiles())
    214 {
    215   if (!ef.isInstalled()) continue;
    216  
    217   JSONObject jsonFile = newJoustFile(jsonByFile, ef, ec);
    218 
    219   List<ExtensionPoint> eps = ef.getObjectsOfClass(ExtensionPoint.class);
    220   Collections.sort(eps, Registry.EXTENSIONPOINT_COMPARATOR);
    221   for (ExtensionPoint ep : eps)
    222   {
    223     newJoustExtensionPoint(jsonFile, ec, ep, ef);
    224   }
    225  
    226   List<Extension> exts = ef.getObjectsOfClass(Extension.class);
    227   Collections.sort(exts, Registry.EXTENSION_COMPARATOR);
    228   String currentGroupId = null;
    229   JSONObject jsonGroup = null;
    230  
    231   for (Extension ext : exts)
    232   {
    233     int groupIndex = ext.getId().indexOf(":");
    234     // ID:s containing ':' should be grouped
    235     if (groupIndex > 0)
    236     {
    237       String groupId = ext.getId().substring(0, groupIndex);
    238       if (!groupId.equals(currentGroupId))
     174try
     175{
     176  dc = sc.newDbControl();
     177  // Build the Joust menu tree
     178  JSONArray jsonJoust = new JSONArray();
     179 
     180  // Two ROOT items:
     181  JSONObject jsonByExtPoint = newJoustEntry(dc, null, "Root", "By extension point", "root.by-extension-point");
     182  jsonByExtPoint.put("isOpen", 1);
     183  JSONObject jsonByFile = newJoustEntry(dc, null, "Root", "By file", "root.by-file");
     184  jsonByFile.put("isOpen", 1);
     185 
     186  // Group some extension points inside sub-folders
     187  JSONObject jsonToolbars = newJoustEntry(dc, jsonByExtPoint, "Folder", "Toolbars", "by-extension-point.toolbars");
     188  JSONObject jsonEditDialogs = newJoustEntry(dc, jsonByExtPoint, "Folder", "Edit dialogs", "by-extension-point.edit-dialogs");
     189  JSONObject jsonListColumns = newJoustEntry(dc, jsonByExtPoint, "Folder", "List columns", "by-extension-point.list-columns");
     190 
     191  jsonJoust.add(jsonByExtPoint);
     192  jsonJoust.add(jsonByFile);
     193 
     194  ExtensionsControl ec = ExtensionsControl.get(dc);
     195  List<ExtensionPoint<?>> extensionPoints = ec.getExtensionPoints();
     196  Collections.sort(extensionPoints, Registry.EXTENSIONPOINT_COMPARATOR);
     197  for (ExtensionPoint ep : extensionPoints)
     198  {
     199    String id = ep.getId();
     200    JSONObject jsonParent = jsonByExtPoint;
     201    if (id.startsWith("net.sf.basedb.clients.web.toolbar.")) jsonParent = jsonToolbars;
     202    if (id.startsWith("net.sf.basedb.clients.web.tabcontrol.edit.")) jsonParent = jsonEditDialogs;
     203    if (id.startsWith("net.sf.basedb.clients.web.onsave.")) jsonParent = jsonEditDialogs;
     204    if (id.startsWith("net.sf.basedb.clients.web.listcolumn.")) jsonParent = jsonListColumns;
     205   
     206    JSONObject jsonEp = newJoustExtensionPoint(dc, jsonParent, ec, ep, ec.getFileByObjectKey(new ExtensionPointKey(ep)));
     207 
     208    List<Extension<?>> extensions = ec.getExtensions(ep.getId());
     209    Collections.sort(extensions, Registry.EXTENSION_COMPARATOR);
     210    for (Extension ext : extensions)
     211    {
     212      newJoustExtension(dc, jsonEp, ec, ext, ec.getFileByObjectKey(new ExtensionKey(ext)), false, true);
     213    }
     214  }
     215 
     216  for (ExtensionsFile ef : ec.getFiles())
     217  {
     218    if (!ef.isInstalled()) continue;
     219   
     220    JSONObject jsonFile = newJoustFile(dc, jsonByFile, ef, ec);
     221 
     222    List<ExtensionPoint> eps = ef.getObjectsOfClass(ExtensionPoint.class);
     223    Collections.sort(eps, Registry.EXTENSIONPOINT_COMPARATOR);
     224    for (ExtensionPoint ep : eps)
     225    {
     226      newJoustExtensionPoint(dc, jsonFile, ec, ep, ef);
     227    }
     228   
     229    List<Extension> exts = ef.getObjectsOfClass(Extension.class);
     230    Collections.sort(exts, Registry.EXTENSION_COMPARATOR);
     231    String currentGroupId = null;
     232    JSONObject jsonGroup = null;
     233   
     234    for (Extension ext : exts)
     235    {
     236      int groupIndex = ext.getId().indexOf(":");
     237      // ID:s containing ':' should be grouped
     238      if (groupIndex > 0)
    239239      {
    240         currentGroupId = groupId;
    241         jsonGroup = newJoustExtensionGroup(jsonFile, ec, ext, currentGroupId);
     240        String groupId = ext.getId().substring(0, groupIndex);
     241        if (!groupId.equals(currentGroupId))
     242        {
     243          currentGroupId = groupId;
     244          jsonGroup = newJoustExtensionGroup(dc, jsonFile, ec, ext, currentGroupId);
     245        }
    242246      }
    243     }
    244     else
    245     {
    246       currentGroupId = null;
    247       jsonGroup = null;
    248     }
    249     newJoustExtension(jsonGroup != null ? jsonGroup : jsonFile, ec, ext, ef, jsonGroup != null, false);
    250   }
    251   List<PluginInfo> plugins = ef.getObjectsOfClass(PluginInfo.class);
    252   Collections.sort(plugins, PluginInfo.NAME_COMPARATOR);
    253   for (PluginInfo info : plugins)
    254   {
    255     newJoustPlugin(jsonFile, ec, info, ef);
    256   }
    257 }
    258 
    259 
    260 try
    261 {
    262   dc = sc.newDbControl();
     247      else
     248      {
     249        currentGroupId = null;
     250        jsonGroup = null;
     251      }
     252      newJoustExtension(dc, jsonGroup != null ? jsonGroup : jsonFile, ec, ext, ef, jsonGroup != null, false);
     253    }
     254    List<PluginInfo> plugins = ef.getObjectsOfClass(PluginInfo.class);
     255    Collections.sort(plugins, PluginInfo.NAME_COMPARATOR);
     256    for (PluginInfo info : plugins)
     257    {
     258      newJoustPlugin(dc, jsonFile, ec, info, ef);
     259    }
     260  }
    263261  %>
    264262  <base:page title="" type="iframe">
  • trunk/www/admin/roles/edit_role.jsp

    r6291 r6684  
    199199            ><label for="act_as_another_user">Act as another user</label><br>
    200200          <input type="checkbox" name="select_jobagent" id="select_jobagent"
    201             <%=PermissionUtil.getPermissionCode(EnumSet.of(Permission.SELECT_JOBAGENT))%>
     201            value="<%=PermissionUtil.getPermissionCode(EnumSet.of(Permission.SELECT_JOBAGENT))%>"
    202202            <%=hasSelectJobagent ? "checked" : ""%>
    203203            ><label for="select_jobagent">Select job agent for jobs</label><br>
  • trunk/www/common/annotations/inherit.js

    r6389 r6684  
    4848  inherit.onSelect = function(event)
    4949  {
     50    var frm = document.forms['annotations'];
    5051    var menuItem = event.target.item;
    5152    if (menuItem.type == 'annotation')
     
    5354      Doc.element('annotationType').innerHTML = menuItem.annotationType;
    5455      Doc.element('annotationValues').innerHTML = menuItem.values;
     56      menuItem.modified = menuItem.inherited != frm[menuItem.id].checked;
    5557    }
    5658    else if (menuItem.type == 'annotation-set')
     
    5860      if (menuItem.children)
    5961      {
    60         var frm = document.forms['annotations'];
    6162        var checked = frm[menuItem.id].checked;
    6263        // If the annotation-set is checked all child items should
     
    6768        {
    6869          var child = menuItem.children[childNo];
    69           frm[child.id].checked = checked || child.inherited;
     70          frm[child.id].checked = checked || (child.inherited != child.modified);
    7071          frm[child.id].disabled = checked;
    7172        }
     
    7374    }
    7475   
    75     inherit.saveInheritedAnnotationsToForm();
    7676  }
    7777 
     
    8686   
    8787    var aFrm = document.forms['annotations'];
    88     var menuElements = tree.getElementsByClassName('menuitem');
     88    var menuElements = tree.getElementsByClassName('joustitem');
    8989    for (var menuNo = 0; menuNo < menuElements.length; menuNo++)
    9090    {
     
    120120      }
    121121    }
    122    
    123122    if (frm.addedAnnotations)
    124123    {
  • trunk/www/common/columns/configure.js

    r6389 r6684  
    122122  {
    123123    var option = new Option(column.title, column.id);
     124    option.title = column.title;
    124125    if (column.alwaysShow)
    125126    {
  • trunk/www/common/overview/failures.js

    r6400 r6684  
    4343    else
    4444    {
    45       var failureId = Data.get(target, 'failure-id');
    4645      var nodeId = Data.get(target, 'node-id');
    4746      window.parent.frames['tree'].Tree.selectNode(nodeId);
  • trunk/www/common/overview/failures.jsp

    r6621 r6684  
    157157          {
    158158            index++;
    159             String failureId = "F" + System.identityHashCode(failure);
    160159            Node node = failure.getNode();
    161160            BasicItem item = node.getItem();
    162161            %>
    163             <tr id="<%=failureId%>" class="failure highlight auto-init" data-auto-init="failure"
    164               data-failure-id="<%=failureId%>" data-node-id="<%=node.getId()%>"
     162            <tr class="failure highlight auto-init" data-auto-init="failure"
     163              data-node-id="<%=node.getId()%>"
    165164              <%
    166165              if (item != null)
  • trunk/www/common/overview/options.jsp

    r6608 r6684  
    8282    width: 17em;
    8383    max-width: 17em;
     84  }
     85 
     86  .special select
     87  {
     88    min-width: 14em;
    8489  }
    8590 
  • trunk/www/common/plugin/parse_file.jsp

    r6621 r6684  
    446446      </div>
    447447     
    448       <div class="absolutefull topborder" style="top: 2em;">
    449 
    450         <table class="fullform input100 special larger">
    451         <tbody class="sectionheader">
    452           <tr>
    453             <th class="rightborder">Property</th>
    454             <th class="rightborder">Mapping expression</th>
    455             <th>File columns</th>
    456           </tr>
    457         </tbody>
    458         <%
    459         for (String name : mappingParameters)
    460         {
    461           %>
    462           <tr class="highlight">
    463             <th><%=HTML.encodeTags(request.getParameter("mapping." + name + ".label"))%></th>
    464             <td>
    465               <table style="width: 100%;">
    466               <tr>
    467                 <td>
    468                 <input type="text" class="text auto-init" data-auto-init="column-mapping"
    469                   name="mapping.<%=name%>.expression"
    470                   maxlength="80"
    471                   value="<%=HTML.encodeTags(request.getParameter("mapping." + name + ".expression"))%>">
    472                 </td>
    473               <td style="width: 22px;">
    474                 <base:icon image="cancel.png" subclass="auto-init" id="<%="clear."+name %>"
    475                   data-auto-init="column-mapping-clear" data-mapping="<%=name%>"
    476                   tooltip="Clear this expression"/>
    477               </td>
    478               </tr>
    479               </table>
    480             </td>
    481             <td style="width: 15em;">
    482               <select name="list.<%=name%>" class="auto-init"
    483                 data-auto-init="column-mapping-preset" data-mapping="<%=name%>">
    484               <option value="">
    485               <%=mappings%>
    486               </select>
    487             </td>
    488           </tr>
    489           <%
    490         }
    491         %>
    492         <tr class="dynamic">
    493           <th></th>
    494           <td></td>
    495           <td></td>
    496         </tr>
    497         </table>
     448      <div class="absolutefull input100" style="top: 2em;">
     449
     450        <tbl:table id="col-mappings">
     451          <tbl:columndef
     452            id="property"
     453            title="Property"
     454          />
     455          <tbl:columndef
     456            id="expression"
     457            title="Mapping expression"
     458          />
     459          <tbl:columndef
     460            id="columns"
     461            title="File columns"
     462          />
     463          <tbl:data>
     464            <tbl:headers>
     465              <tbl:headerrow>
     466                <tbl:columnheaders />
     467              </tbl:headerrow>
     468            </tbl:headers>           
     469            <tbl:rows>
     470            <%
     471            for (String name : mappingParameters)
     472            {
     473              %>
     474              <tbl:row>
     475                <tbl:cell column="property"><%=HTML.encodeTags(request.getParameter("mapping." + name + ".label"))%></tbl:cell>
     476                <tbl:cell column="expression">
     477               
     478                    <table style="width: 100%;">
     479                    <tr>
     480                      <td>
     481                      <input type="text" class="text auto-init" data-auto-init="column-mapping"
     482                        name="mapping.<%=name%>.expression"
     483                        maxlength="80"
     484                        value="<%=HTML.encodeTags(request.getParameter("mapping." + name + ".expression"))%>">
     485                      </td>
     486                    <td style="width: 22px;">
     487                      <base:icon image="cancel.png" subclass="auto-init" id="<%="clear."+name %>"
     488                        data-auto-init="column-mapping-clear" data-mapping="<%=name%>"
     489                        tooltip="Clear this expression"/>
     490                    </td>
     491                    </tr>
     492                    </table>
     493                </tbl:cell>
     494               
     495                <tbl:cell column="columns">
     496                  <select name="list.<%=name%>" class="auto-init"
     497                    data-auto-init="column-mapping-preset" data-mapping="<%=name%>">
     498                  <option value="">
     499                  <%=mappings%>
     500                  </select>
     501                </tbl:cell>
     502             
     503              </tbl:row>
     504              <%
     505            }
     506            %>
     507            </tbl:rows>
     508          </tbl:data>
     509        </tbl:table>
    498510      </div>
    499511    </form>
  • trunk/www/filemanager/select_file.jsp

    r6540 r6684  
    4242
    4343<base:body>
    44   <h1><%=requestTitle == null ? title : requestTitle%></h1>
     44  <h1 style="border-bottom-width: 0;"><%=requestTitle == null ? title : requestTitle%></h1>
    4545  <div class="content bottomborder">
    4646    <div id="page-data" class="datacontainer"
  • trunk/www/include/scripts/main-2.js

    r6621 r6684  
    24102410  {
    24112411    list = Doc.element(list);
    2412     if (list.style.width)
    2413     {
    2414       forms.checkOptionText(list.style.width, option);
     2412    if (option.hasAttribute('text') && !option.hasAttribute('title'))
     2413    {
     2414      option.title = option.text;
    24152415    }
    24162416    if (index < 0 || index >= list.length)
     
    24252425  }
    24262426 
    2427   /**
    2428     Check the length text attribute of a selection list option against
    2429     the width of the selection list. If the text is longer than what
    2430     can be displayed in the list, the text is automatically shortened
    2431     and ... is appended. The full text is made available as a popup
    2432     tooltip. If the text ends with a part inside brackets, [],
    2433     that part is preserved, chopping is done on the text preceeding it.
    2434     @param listWidth Width og the list including unit (em or px is supported)
    2435     @param option The option that is beeing added to the list
    2436   */
    2437   forms.checkOptionText = function(listWidth, option)
    2438   {
    2439     var width = listWidth.match(/(\d+)(em|px)/);
    2440     if (width == null) return;
    2441     var maxLength;
    2442     if (width[2] == 'em')
    2443     {
    2444       maxLength = 1.2 * width[1] + 0.01 * width[1] * width[1];
    2445     }
    2446     else
    2447     {
    2448       maxLength = 0.1 * width[1];
    2449     }
    2450     var hellip = String.fromCharCode(8230);
    2451     if (option.text && option.text.length > maxLength)
    2452     {
    2453       var text = option.text;
    2454       option.title = text;
    2455       var parts = text.match(/(.*)\[(.*)\]/);
    2456       if (parts != null)
    2457       {
    2458         maxLength = maxLength - parts[2].length - 3;
    2459         if (maxLength < 4) maxLength = 4;
    2460         text = parts[1].substring(0, maxLength) + hellip + ' [' + parts[2] + ']';
    2461       }
    2462       else
    2463       {
    2464         text = text.substring(0, maxLength) + hellip;
    2465       }
    2466       option.text = text;
    2467     }
    2468   }
    2469 
    24702427  /**
    24712428    Switch place of two options in a list
  • trunk/www/info/about.jsp

    r6610 r6684  
    3838  import="java.sql.Driver"
    3939  import="java.util.Properties"
     40  import="java.util.List"
     41  import="java.lang.management.ManagementFactory"
     42  import="java.lang.management.MemoryPoolMXBean"
     43  import="java.lang.management.MemoryType"
     44  import="java.lang.management.MemoryUsage"
    4045%>
    4146<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
     
    6368final Properties properties = System.getProperties();
    6469final Runtime runtime = Runtime.getRuntime();
    65 
     70List<MemoryPoolMXBean> beans = ManagementFactory.getMemoryPoolMXBeans();
    6671%>
    6772<base:page type="popup" title="About">
    68 <base:head scripts="tabcontrol-2.js,~info.js" styles="tabcontrol.css" />
     73<base:head scripts="tabcontrol-2.js,~info.js" styles="tabcontrol.css">
     74<style>
     75#memoryTable th, #memoryTable td
     76{
     77  text-align: right;
     78  padding-left: 1em;
     79  padding-right: 1.5em;
     80}
     81
     82.memory-warning
     83{
     84  color: #C80000;
     85  font-weight: bold;
     86  background-image: url('../images/warning_small.png');
     87  background-repeat: no-repeat;
     88  background-position: 100% 50%;
     89}
     90</style>
     91</base:head>
    6992<base:body data-read-only="1">
    7093  <h1>BASE - BioArray Software Environment</h1>
     
    135158      </td>
    136159  </tr>
    137   <tr>
     160  <tr class="dynamic">
    138161    <th>Memory</th>
    139     <td class="info">Total: <%=Values.formatBytes(runtime.totalMemory())%><br>
    140       Free: <%=Values.formatBytes(runtime.freeMemory()) %><br>
    141       Max: <%=Values.formatBytes(runtime.maxMemory()) %></td>
    142   </tr>
    143   <tr class="dynamic">
    144     <th></th>
    145     <td></td>
     162    <td class="info">
     163     
     164      <table id="memoryTable" style="xwidth:100%;">
     165      <tr style="border-bottom-width: 1px;">
     166        <th></th>
     167        <th>Used</th>
     168        <th>Max</th>
     169        <th></th>
     170      </tr>
     171      <%
     172      for (MemoryType mtype : MemoryType.values())
     173      {
     174        long sumUsed = 0;
     175        long sumMax = 0;
     176        for (MemoryPoolMXBean mbean : beans)
     177        {
     178          if (mbean.getType() == mtype)
     179          {
     180            MemoryUsage usage = mbean.getUsage();
     181            sumUsed += usage.getUsed();
     182            sumMax += usage.getMax();
     183            long percent = 100*usage.getUsed() / usage.getMax();
     184            %>
     185            <tr>
     186            <td><%=mbean.getName() %></td>
     187            <td><%=Values.formatBytes(usage.getUsed()) %></td>
     188            <td><%=Values.formatBytes(usage.getMax()) %></td>
     189            <td class="<%=percent > 75 ? "memory-warning" : "" %>"><%=percent %>%</td>
     190            </tr>
     191          <%
     192          }
     193        }
     194        %>
     195        <tr style="border-bottom-width: 1px; font-weight: bold;">
     196          <td>Sum <%=mtype.toString() %></td>
     197          <td><%=Values.formatBytes(sumUsed) %></td>
     198          <td><%=Values.formatBytes(sumMax) %></td>
     199          <td><%=100*sumUsed / sumMax %>%</td>
     200        </tr>
     201        <%
     202      }
     203      %>
     204     
     205      </table>
    146206  </tr>
    147207  </table>
  • trunk/www/lims/arrayslides/create_wizard.jsp

    r6312 r6684  
    192192          <tbody class="sectionheader">
    193193          <tr>
    194             <th>&nbsp;</th>
    195             <th>Name:
     194            <th style="border-top-width: 0;">&nbsp;</th>
     195            <th style="border-top-width: 0;">Name:
    196196              <base:icon
    197197                id="pasteMultipleName"
     
    207207              />
    208208            </th>
    209             <th>Barcode:
     209            <th style="border-top-width: 0;">Barcode:
    210210              <base:icon
    211211                id="pasteMultipleBarcode"
  • trunk/www/views/experiments/index.jsp

    r6315 r6684  
    453453    cloneJob.setParameterValue("cloneSource", "Clone source", null,
    454454      new StringParameterType(), request.getParameter("cloneSource"));
     455    cloneJob.setScheduled(null, null);
    455456    dc.saveItem(cloneJob);
    456457    dc.commit();
  • trunk/www/views/jobs/view_job.jsp

    r6621 r6684  
    303303              %>
    304304              <td style="padding-left: 10px;"><base:button
    305                 subclass="link auto-init"
     305                subclass="auto-init"
    306306                data-auto-init="view-file"
    307307                data-file-id="<%=logFile.getId()%>"
  • trunk/www/views/physicalbioassays/list_bioassays.jsp

    r6604 r6684  
    235235        id="derivedBioAssays"
    236236        title="Derived bioassays"
    237         property="&rootDerivedBioAssays(name)"
     237        property="&rootDerivedBioAssays(%name)"
    238238        datatype="string"
    239239        filterable="true"
Note: See TracChangeset for help on using the changeset viewer.