Changeset 2527


Ignore:
Timestamp:
01/31/13 15:55:57 (11 years ago)
Author:
yana
Message:

Logging organized, progress info about waiting for search results added, SRUThreadedClient is one per application now.

Location:
SRUAggregator/trunk
Files:
12 edited
1 moved

Legend:

Unmodified
Added
Removed
  • SRUAggregator/trunk/pom.xml

    r2502 r2527  
    44    <groupId>eu.clarin.sru.fcs</groupId>
    55    <artifactId>aggregator</artifactId>
    6     <version>1.0-SNAPSHOT</version>
     6    <version>1.0</version>
    77    <properties>
    88        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
     
    5454            <artifactId>sru-client</artifactId>
    5555            <version>0.9.0</version>
     56        </dependency>
     57        <dependency>
     58            <groupId>eu.clarin.weblicht</groupId>
     59            <artifactId>wlfxb</artifactId>
     60            <version>1.2.2</version>
    5661        </dependency>
    5762    </dependencies>
  • SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/app/Aggregator.java

    r2502 r2527  
    33import com.google.gson.Gson;
    44import com.google.gson.reflect.TypeToken;
    5 import eu.clarin.sru.client.SRUClientException;
    6 import eu.clarin.sru.client.SRUExplainRequest;
    7 import eu.clarin.sru.client.SRUExplainResponse;
    8 import eu.clarin.sru.client.SRURecord;
    9 import eu.clarin.sru.client.SRUSearchRetrieveRequest;
    10 import eu.clarin.sru.client.SRUSearchRetrieveResponse;
    11 import eu.clarin.sru.client.SRUSurrogateRecordData;
    12 import eu.clarin.sru.client.SRUThreadedClient;
    135import eu.clarin.sru.client.SRUVersion;
    14 import eu.clarin.sru.client.fcs.ClarinFCSRecordData;
    15 import eu.clarin.sru.client.fcs.ClarinFCSRecordParser;
    16 import eu.clarin.sru.client.fcs.DataView;
    17 import eu.clarin.sru.client.fcs.DataViewKWIC;
    18 import eu.clarin.sru.client.fcs.Resource;
    196import eu.clarin.sru.fcs.aggregator.data.CenterRegistry;
    207import eu.clarin.sru.fcs.aggregator.sparam.CorpusTreeModel;
     
    2310import java.lang.reflect.Type;
    2411import java.util.ArrayList;
    25 import java.util.Arrays;
    26 import java.util.HashSet;
    2712import java.util.LinkedHashMap;
    2813import java.util.List;
    2914import java.util.Map;
    3015import java.util.Set;
    31 import java.util.concurrent.ExecutionException;
    32 import java.util.concurrent.Future;
    3316import java.util.logging.*;
    34 import org.zkoss.zhtml.Filedownload;
    3517import org.zkoss.zk.ui.Component;
    36 import org.zkoss.zk.ui.Desktop;
    3718import org.zkoss.zk.ui.Executions;
    3819import org.zkoss.zk.ui.event.Event;
    39 import org.zkoss.zk.ui.event.EventListener;
    4020import org.zkoss.zk.ui.select.SelectorComposer;
    4121import org.zkoss.zk.ui.select.annotation.Listen;
    4222import org.zkoss.zk.ui.select.annotation.Wire;
    43 import org.zkoss.zul.Auxhead;
    44 import org.zkoss.zul.Auxheader;
    4523import org.zkoss.zul.Button;
    46 import org.zkoss.zul.Checkbox;
    47 import org.zkoss.zul.Column;
    48 import org.zkoss.zul.Columns;
    4924import org.zkoss.zul.Combobox;
    5025import org.zkoss.zul.Comboitem;
    51 import org.zkoss.zul.Grid;
    5226import org.zkoss.zul.Groupbox;
    5327import org.zkoss.zul.Iframe;
    5428import org.zkoss.zul.Label;
     29import org.zkoss.zul.Menuitem;
    5530import org.zkoss.zul.Messagebox;
    56 import org.zkoss.zul.Row;
    57 import org.zkoss.zul.Rows;
    58 import org.zkoss.zul.Separator;
    5931import org.zkoss.zul.Textbox;
    6032import org.zkoss.zul.Tree;
    6133import org.zkoss.zul.Treechildren;
    6234import org.zkoss.zul.Treeitem;
    63 import org.zkoss.zul.Vbox;
    6435import org.zkoss.zul.Window;
    6536import org.zkoss.zul.event.ZulEvents;
     
    7243public class Aggregator extends SelectorComposer<Component> {
    7344
    74     private static final Logger logger = Logger.getLogger("FCS-AGGREGATOR");
     45    private static final Logger logger = Logger.getLogger(Aggregator.class.getName());
     46   
    7547//    @Wire
    7648//    private Grid anzeigeGrid;
     
    7951    @Wire
    8052    private Combobox languageSelect;
    81     @Wire
    82     private Button searchButton;
    83     @Wire
    84     private Groupbox allCorpora;
     53//    @Wire
     54//    private Button searchButton;
     55//    @Wire
     56//    private Groupbox allCorpora;
    8557//    @Wire
    8658//    private Comboitem german;
     
    8961    @Wire
    9062    private Window resultsBox;
    91     @Wire
    92     private Button selectAll;
    93     @Wire
    94     private Button deselectAll;
    95     @Wire
    96     private Window mainWindow;
     63//    @Wire
     64//    private Button selectAll;
     65//    @Wire
     66//    private Button deselectAll;
     67//    @Wire
     68//    private Window mainWindow;
    9769    @Wire
    9870    private Combobox maximumRecordsSelect;
    99     @Wire
    100     private Button addForeignEndpoint;
     71//    @Wire
     72//    private Button addForeignEndpoint;
    10173    @Wire
    10274    Combobox foreignEndpointSelect;
    10375    @Wire
    10476    private Tree tree;
     77    @Wire
     78    private Label searchResultsProgress;
     79   
    10580    private Map<String, List<String>> xAggregationContext;
     81    private SRUVersion version = SRUVersion.VERSION_1_2;
    10682    private SearchResultsController searchResultsController;
    10783    private CenterRegistry registry;
     
    10985    @Override
    11086    public void doAfterCompose(Component comp) throws Exception {
     87       
    11188        super.doAfterCompose(comp);
    11289
     
    11491
    11592        languageSelect.setSelectedItem(anyLanguage);
    116         searchResultsController = new SearchResultsController(resultsBox);
    117         // assign it to desktop, so that it can be accessed to be shutdown when the desktop is destroyed
    118         // TODO the registry/tree also has to be shutdown properly???
     93       
     94        searchResultsController = new SearchResultsController(resultsBox, searchResultsProgress);
     95        // assign the search controller to desktop, so that it can be accessed to be shutdown when the desktop is destroyed
    11996        Executions.getCurrent().getDesktop().setAttribute(searchResultsController.getClass().getSimpleName(), searchResultsController);
     97        // also add it to the list of actice controllers of the web application, so that they can be shutdown when the application stops
     98        Set<SearchResultsController> activeControllers = (Set<SearchResultsController>) Executions.getCurrent().getDesktop().getWebApp().getAttribute(WebAppListener.ACTIVE_SEARCH_CONTROLLERS);
     99        activeControllers.add(searchResultsController);
    120100       
    121101        registry = new CenterRegistry();
     
    158138    public void onExecuteSearch(Event ev) {
    159139        int maxRecords = Integer.parseInt(maximumRecordsSelect.getValue());
    160         logger.info("Executing Search.");
    161         searchResultsController.executeSearch(tree.getSelectedItems(), maxRecords, searchString.getText());
     140        searchResultsController.executeSearch(tree.getSelectedItems(), maxRecords, searchString.getText(), version);
    162141    }
    163142 
     
    185164    @Listen("onClick=#exportResultsCSV")
    186165    public void onExportResultsCSV(Event ev) {
    187 
    188         int i, i2, i3;
    189         String temp = "";
    190         boolean somethingToExport = false;
    191 
    192         for (i = 0; i < resultsBox.getChildren().size(); i++) {
    193             if (resultsBox.getChildren().get(i) instanceof Grid) {
    194                 somethingToExport = true;
    195                 Grid aGrid = (Grid) resultsBox.getChildren().get(i);
    196                 Rows rows = aGrid.getRows();
    197 
    198                 for (i2 = 0; i2 < rows.getChildren().size(); i2++) {
    199                     Row r = (Row) rows.getChildren().get(i2);
    200 
    201                     for (i3 = 0; i3 < r.getChildren().size(); i3++) {
    202                         Label l = (Label) r.getChildren().get(i3);
    203                         temp = temp + "\"" + l.getValue().replace("\"", "QUOTE") + "\"";
    204                         if (i3 < r.getChildren().size() - 1) {
    205                             temp = temp + ",";
    206                         } //if i3
    207                     } //for i3
    208                     temp = temp + "\n";
    209                 } // for i2
    210             } // if grid
    211 
    212         } // for i ...
    213 
    214         if (somethingToExport) {
    215 
    216             Filedownload.save(temp, "text/plain", "ClarinDFederatedContentSearch.csv");
    217         } else {
    218             Messagebox.show("Nothing to export!");
    219         }
     166        searchResultsController.exportCSV();
    220167    }
    221168
    222169    @Listen("onClick=#exportResultsTCF")
    223170    public void onExportResultsTCF(Event ev) {
    224 
    225         int i, i2, i3;
    226         String temp = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><D-Spin xmlns=\"http://www.dspin.de/data\" version=\"0.4\">\n<MetaData xmlns=\"http://www.dspin.de/data/metadata\">\n";
    227         temp = temp + "<source>CLARIN-D Federated Content Search</source>\n</MetaData>\n  <TextCorpus xmlns=\"http://www.dspin.de/data/textcorpus\" lang=\"de\">\n<text>";
    228 
    229 
    230         boolean somethingToExport = false;
    231 
    232         for (i = 0; i < resultsBox.getChildren().size(); i++) {
    233             if (resultsBox.getChildren().get(i) instanceof Grid) {
    234                 somethingToExport = true;
    235                 Grid aGrid = (Grid) resultsBox.getChildren().get(i);
    236                 Rows rows = aGrid.getRows();
    237 
    238                 for (i2 = 0; i2 < rows.getChildren().size(); i2++) {
    239                     Row r = (Row) rows.getChildren().get(i2);
    240 
    241                     for (i3 = 0; i3 < r.getChildren().size(); i3++) {
    242                         Label l = (Label) r.getChildren().get(i3);
    243                         temp = temp + l.getValue() + " ";
    244                     } //for i3
    245                     temp = temp + "\n";
    246                 } // for i2
    247             } // if grid
    248 
    249         } // for i ...
    250 
    251         if (somethingToExport) {
    252             temp = temp + "</text>\n</TextCorpus>\n</D-Spin>";
    253             Filedownload.save(temp, "text/tcf+xml", "ClarinDFederatedContentSearch.xml");
    254         } else {
    255             Messagebox.show("Nothing to export!");
    256         }
     171        searchResultsController.exportTCF();
    257172    }
    258173   
     
    263178
    264179    private void processParameters() {
     180       
    265181        String[] paramValue;
    266182        String contextJson = null;
    267183
    268         //TODO use them???
    269         String operationString = null;
    270         String versionString = null;
    271 
    272184        paramValue = Executions.getCurrent().getParameterMap().get("query");
    273185        if (paramValue != null) {
    274             searchString.setValue(paramValue[0]);
     186            searchString.setValue(paramValue[0].trim());
     187            logger.log(Level.INFO, "Received parameter: query[{0}]",  searchString.getValue());
    275188        }
    276189        paramValue = Executions.getCurrent().getParameterMap().get("operation");
    277190        if (paramValue != null) {
    278             operationString = paramValue[0];
     191            String operationString = paramValue[0].trim();
     192            logger.log(Level.INFO, "Received parameter: operation[{0}]", operationString);
    279193            if (!operationString.equals("searchRetrieve")) {
    280                 logger.severe("Not supported operation: " + operationString);
     194                logger.log(Level.SEVERE, "Not supported operation: {0}", operationString);
     195                Messagebox.show("CLARIN-D Federated Content Search Aggregator\n\nVersion 0.0.1", "FCS", 0, Messagebox.INFORMATION);
    281196            }
    282197        }
    283198        paramValue = Executions.getCurrent().getParameterMap().get("version");
    284199        if (paramValue != null) {
    285             versionString = paramValue[0];
     200            String versionString = paramValue[0].trim();
     201            logger.log(Level.INFO, "Received parameter: version[{0}]", versionString);
     202            if (versionString.equals("1.2")) {
     203                version = SRUVersion.VERSION_1_2;
     204            } else if (versionString.equals("1.1")) {
     205                version = SRUVersion.VERSION_1_1;
     206            } else {
     207                logger.log(Level.SEVERE, "Not supported SRU version: {0}", versionString);
     208                Messagebox.show("SRU Version " + version + " not supported", "FCS", 0, Messagebox.INFORMATION);
     209            }
    286210        }
    287211        paramValue = Executions.getCurrent().getParameterMap().get("x-aggregation-context");
    288212        if (paramValue != null) {
    289             contextJson = paramValue[0];
    290         }
    291 
    292         logger.info("query: " + searchString.getValue());
    293         logger.info("operation: " + operationString);
    294         logger.info("version: " + versionString);
    295         logger.info("x-aggregation-context: " + contextJson);
     213            contextJson = paramValue[0].trim();
     214            logger.log(Level.INFO, "Received parameter: x-aggregation-context[{0}]", contextJson);
     215        }
    296216
    297217        if (contextJson != null) {
     
    299219            Type mapType = new TypeToken<LinkedHashMap<String, ArrayList<String>>>() {
    300220            }.getType();
     221            try {
    301222            this.xAggregationContext = gson.fromJson(contextJson, mapType);
    302             //System.out.println("selectedEndpoints: " + selectedEndpoints);
    303             //selectEndpoints(selectedEndpoints);
    304         }
    305 
     223            } catch (Exception ex) {
     224                logger.log(Level.SEVERE, "Error parsing JSON from x-aggregation-context:\n {0}\n {1}", new String[]{ex.getMessage(), contextJson});
     225                Messagebox.show("Error in x-aggregation-context parameter", "FCS", 0, Messagebox.INFORMATION);
     226            }
     227        }
    306228
    307229    }
  • SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/app/DesktopDestroyedListener.java

    r2502 r2527  
    33
    44import eu.clarin.sru.fcs.aggregator.sresult.SearchResultsController;
     5import java.util.Set;
    56import java.util.logging.Logger;
    67import org.zkoss.zk.ui.Desktop;
     
    1213 */
    1314public class DesktopDestroyedListener implements DesktopCleanup {
     15   
     16    private static final Logger logger = Logger.getLogger(DesktopCleanup.class.getName());
    1417
    1518    @Override
    1619    public void cleanup(Desktop desktop) {
    17 
     20        logger.fine("Cleaning up desktop...");
    1821        Object recordsController = desktop.getAttribute(SearchResultsController.class.getSimpleName());
     22        Set<SearchResultsController> activeControllers = (Set<SearchResultsController>) desktop.getWebApp().getAttribute(WebAppListener.ACTIVE_SEARCH_CONTROLLERS);
    1923        if (recordsController != null) {
    20             Logger.getLogger(DesktopDestroyedListener.class.getName()).info("Cleaning up desktop");
    21             ((SearchResultsController) recordsController).shutdown();
     24            SearchResultsController srController = (SearchResultsController) recordsController;
     25            srController.shutdown();
     26            activeControllers.remove(srController);
    2227        }
    2328    }
  • SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/app/WebAppListener.java

    r2508 r2527  
    11package eu.clarin.sru.fcs.aggregator.app;
    22
    3 
     3import eu.clarin.sru.client.SRUClientException;
     4import eu.clarin.sru.client.SRUThreadedClient;
     5import eu.clarin.sru.client.fcs.ClarinFCSRecordParser;
     6import eu.clarin.sru.fcs.aggregator.sresult.SearchResultsController;
     7import java.util.HashSet;
     8import java.util.Set;
     9import java.util.logging.Level;
    410import java.util.logging.Logger;
    511import org.zkoss.zk.ui.WebApp;
    612import org.zkoss.zk.ui.util.WebAppCleanup;
     13import org.zkoss.zk.ui.util.WebAppInit;
    714
    815/**
     
    1017 * @author Yana Panchenko
    1118 */
    12 public class WebAppDestroyedListener implements WebAppCleanup {
     19public class WebAppListener implements WebAppInit, WebAppCleanup {
     20
     21    public static String ACTIVE_SEARCH_CONTROLLERS = "ACTIVE_SEARCH_CONTROLLERS";
     22    public static String SHARED_SRU_CLIENT = "SHARED_SRU_CLIENT";
     23    private static final Logger logger = Logger.getLogger(WebAppListener.class.getName());
    1324
    1425    @Override
    15     public void cleanup(WebApp wapp) throws Exception {
    16         //TODO
    17         Logger.getLogger(WebAppDestroyedListener.class.getName()).info("TODO: WebAppDestroyedListener");
     26    public void init(WebApp webapp) throws Exception {
     27
     28        //int endOfClassesSharedPartOfName = WebAppListener.class.getPackage().getName().lastIndexOf(".");
     29        //Logger.getLogger(WebAppListener.class.getPackage().getName().substring(0, endOfClassesSharedPartOfName)).setLevel(Level.FINE);
     30       
     31        logger.info("Aggregator is starting...");
     32       
     33        Set<SearchResultsController> activeControllers = new HashSet<SearchResultsController>();
     34        webapp.setAttribute(ACTIVE_SEARCH_CONTROLLERS, activeControllers);
     35
     36        SRUThreadedClient searchClient = new SRUThreadedClient();
     37        try {
     38            searchClient.registerRecordParser(new ClarinFCSRecordParser());
     39            webapp.setAttribute(WebAppListener.SHARED_SRU_CLIENT, searchClient);
     40        } catch (SRUClientException e) {
     41            logger.log(Level.SEVERE, "SRU Client Parser registration failed", e);
     42        }
     43    }
     44
     45    @Override
     46    public void cleanup(WebApp webapp) throws Exception {
     47        logger.info("Aggregator is shutting down...");
     48
     49        Set<SearchResultsController> activeControllers = (Set<SearchResultsController>) webapp.getAttribute(ACTIVE_SEARCH_CONTROLLERS);
     50        for (SearchResultsController activeController : activeControllers) {
     51            activeController.shutdown();
     52        }
     53        SRUThreadedClient searchClient = (SRUThreadedClient) webapp.getAttribute(WebAppListener.SHARED_SRU_CLIENT);
     54
     55        // with shutdown() there are memory leaks when web app stops even if all requests have been processed;
     56        // with shutdownNow() there are memory leaks when web app stops only if not all requests have been processed
     57        searchClient.shutdownNow();
    1858    }
    1959}
  • SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/data/CenterRegistry.java

    r2502 r2527  
    77
    88import eu.clarin.sru.fcs.aggregator.sparam.CorpusTreeNode;
     9import java.io.IOException;
    910import java.io.InputStream;
    1011import java.net.URL;
     
    2930public class CenterRegistry implements CorpusTreeNode {
    3031   
    31     private static final Logger logger = Logger.getLogger("FCS-AGGREGATOR");
     32    private static final Logger logger = Logger.getLogger(CenterRegistry.class.getName());
    3233
    3334    private static final String crStartpoint = "http://130.183.206.32/restxml/";
    3435
    3536    //https://centerregistry-clarin.esc.rzg.mpg.de/restxml/
    36     //http://130.183.206.32/restxml/
    3737   
    3838    private boolean hasChildrenLoaded = false;
     
    5151        }
    5252        hasChildrenLoaded = true;
    53         InputStream is;
     53        InputStream is = null;
    5454        URL u;
    5555        NodeList instituteNames;
     
    5757        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    5858        DocumentBuilder builder;
     59        URLConnection urlConn;
    5960        try {
    6061            u = new URL(crStartpoint);
    61             URLConnection urlConn = u.openConnection();
     62            urlConn = u.openConnection();
    6263
    6364            //HttpsURLConnection urlConn = (HttpsURLConnection) u.openConnection();
     
    7576            org.w3c.dom.Document document = builder.parse(is);
    7677
    77             is.close();
     78           
    7879            instituteNames = evaluateXPath("//Centername", document);
    7980            institutionsUrls = evaluateXPath("//Center_id_link", document);
     
    9091
    9192        } catch (Exception ex) {
    92             logger.log(Level.SEVERE, "Error accessing central repository information", ex);
     93            logger.log(Level.SEVERE, "Error accessing central registry information {0} {1}", new String[]{ex.getClass().getName(), ex.getMessage()});
     94        } finally {
     95            if (is != null) {
     96                try {
     97                    is.close();
     98                } catch (IOException ex) {
     99                    logger.log(Level.SEVERE, ex.getMessage());
     100                }
     101            }
    93102        }
    94         logger.info(String.format("Number of Centers: %s", centers.size()));
     103        logger.log(Level.FINE, "Number of Centers: {0}", centers.size());
    95104
    96105    }
  • SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/data/Corpus.java

    r2502 r2527  
    2727    private boolean hasChildrenLoaded = false;
    2828    private Endpoint endpoint;
    29     // private String endpointUrl;
     29   
     30    private static final Logger logger = Logger.getLogger(Corpus.class.getName());
    3031   
    3132    public Corpus(Endpoint endpoint) {
     
    135136            corporaResponse = sruClient.scan(corporaRequest);
    136137        } catch (SRUClientException ex) {
    137             Logger.getLogger(Endpoint.class.getName()).log(Level.SEVERE, "Error accessing corpora " + value + " at " + endpoint.getUrl(), ex);
     138            logger.log(Level.SEVERE, "Error accessing corpora {0} at {1}\n {2} {3}",
     139                    new String[]{value, endpoint.getUrl(), ex.getClass().getName(), ex.getMessage()});
    138140        }
    139141        if (corporaResponse != null && corporaResponse.hasTerms()) {
     
    147149        }
    148150    }
     151   
    149152}
  • SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/data/Endpoint.java

    r2502 r2527  
    2323    private List<Corpus> corpora;
    2424    private boolean hasChildrenLoaded = false;
     25   
     26    private static final Logger logger = Logger.getLogger(Endpoint.class.getName());
    2527
    2628    public Endpoint(String url, Institution institution) {
     
    6365        }
    6466        this.hasChildrenLoaded = true;
    65         //this.corpora = EndpointY.getCorpora(url);
    6667        loadChildCorpora();
    6768    }
     
    8081        }
    8182        return corpora.get(index);
    82     }
    83 
    84 //    public static ArrayList<CorpusY> getCorpora(String endpointUrl) {
    85 //        return getCorpora(endpointUrl, ""); //TODO to be changed to 'root'
    86 //    }
    87 //
    88 //    public static ArrayList<CorpusY> getCorpora(String endpointUrl, String resourceHandler) {
    89 //
    90 //        ArrayList<CorpusY> corpora = new ArrayList<CorpusY>();
    91 //        SRUScanResponse corporaResponse = null;
    92 //        StringBuilder scanClause = new StringBuilder("fcs.resource");
    93 //        if (resourceHandler.length() > 0) {
    94 //            scanClause.append("=");
    95 //        }
    96 //        scanClause.append(resourceHandler);
    97 //        try {
    98 //            SRUClient sruClient = new SRUClient(SRUVersion.VERSION_1_2);
    99 //            SRUScanRequest corporaRequest = new SRUScanRequest(endpointUrl);
    100 //            corporaRequest.setScanClause(scanClause.toString());
    101 //            //TODO extra data?
    102 //            //corporaRequest.setExtraRequestData("x-cmd-resource-info", "true");
    103 //            corporaResponse = sruClient.scan(corporaRequest);
    104 //        } catch (SRUClientException ex) {
    105 //            Logger.getLogger(EndpointY.class.getName()).log(Level.SEVERE, "Error accessing corpora at " + endpointUrl + " for " + resourceHandler, ex);
    106 //        }
    107 //        if (corporaResponse != null && corporaResponse.hasTerms()) {
    108 //            for (SRUTerm term : corporaResponse.getTerms()) {
    109 //                CorpusY c = new CorpusY(endpointUrl);
    110 //                c.setValue(term.getValue());
    111 //                c.setDisplayTerm(term.getDisplayTerm());
    112 //                c.setNumberOfRecords(term.getNumberOfRecords());
    113 //                corpora.add(c);
    114 //            }
    115 //        }
    116 //        return corpora;
    117 //
    118 //    }
    119    
     83    } 
    12084
    12185    private void loadChildCorpora() {
     
    13296            corporaResponse = sruClient.scan(corporaRequest);
    13397        } catch (SRUClientException ex) {
    134             Logger.getLogger(Endpoint.class.getName()).log(Level.SEVERE, "Error accessing corpora at " + url, ex);
     98            logger.log(Level.SEVERE, "Error accessing corpora at {0}\n {1}\n {2}", new String[]{url, ex.getClass().getName(), ex.getMessage()});
    13599        }
    136100        if (corporaResponse != null && corporaResponse.hasTerms()) {
  • SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/data/Institution.java

    r2502 r2527  
    33import eu.clarin.sru.fcs.aggregator.sparam.CorpusTreeNode;
    44import eu.clarin.sru.fcs.aggregator.data.CenterRegistry;
     5import java.io.IOException;
    56import java.io.InputStream;
    67import java.net.URL;
     
    2425    private ArrayList<Endpoint> endpoints;
    2526    private boolean hasChildrenLoaded = false;
    26     private static final Logger logger = Logger.getLogger("FCS-AGGREGATOR");
     27   
     28    private static final Logger logger = Logger.getLogger(Institution.class.getName());
    2729
    2830    public Institution(String name, String link) {
     
    5254        }
    5355        hasChildrenLoaded = true;
    54         InputStream is;
    55         URL u;
    56         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    57         DocumentBuilder builder;
    58         Document doc;
    59 
     56        InputStream is = null;
     57       
    6058        try {
    61             builder = factory.newDocumentBuilder();
    62             u = new URL(link);
     59            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
     60            DocumentBuilder builder = factory.newDocumentBuilder();
     61            URL u = new URL(link);
    6362            is = u.openStream();
    64             doc = builder.parse(is);
     63            Document doc = builder.parse(is);
    6564            is.close();
    66             NodeList endpointsUrls = CenterRegistry.evaluateXPath("//WebReference[./Description[text()=\"CQL\"]]/Website", doc);
     65            NodeList endpointsUrls = CenterRegistry
     66                    .evaluateXPath("//WebReference[./Description[text()=\"CQL\"]]/Website", doc);
    6767
    6868            for (int j = 0; j < endpointsUrls.getLength(); j++) {
     
    7272            }
    7373        } catch (Exception ex) {
    74             logger.log(Level.SEVERE, String.format("Error accessing endpoints of %s", link), ex);
     74            logger.log(Level.SEVERE, "Error accessing endpoint of {0}\n {1}\n {2}",
     75                    new String[]{link, ex.getClass().getName(), ex.getMessage()});
     76        } finally {
     77            if (is != null) {
     78                try {
     79                    is.close();
     80                } catch (IOException ex) {
     81                    logger.log(Level.SEVERE, null, ex);
     82                }
     83            }
    7584        }
    7685    }
  • SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/data/SearchResult.java

    r2502 r2527  
    66
    77import eu.clarin.sru.client.SRUSearchRetrieveResponse;
     8import eu.clarin.sru.client.fcs.DataViewKWIC;
     9import java.util.ArrayList;
     10import java.util.List;
    811import java.util.concurrent.Future;
    912import java.util.logging.Level;
     
    2326    private Future<SRUSearchRetrieveResponse> futureResponse;
    2427    private SRUSearchRetrieveResponse response;
     28    private List<DataViewKWIC> dataKWIC = new ArrayList<DataViewKWIC>();
     29   
     30    private static final Logger logger = Logger.getLogger(SearchResult.class.getName());
     31
     32    public List<DataViewKWIC> getDataKWIC() {
     33        return dataKWIC;
     34    }
     35
     36    public void addKWIC(DataViewKWIC kw) {
     37        this.dataKWIC.add(kw);
     38    }
     39   
    2540
    2641    public SearchResult(Object nodeData) {
     
    8095            }
    8196        } catch (Exception ex) {
    82             Logger.getLogger(SearchResult.class.getName()).log(Level.SEVERE, null, ex);
     97            logger.log(Level.SEVERE, "Error consuming response from {0} {1}\n {2}\n {3}",
     98                    new Object[]{endpoint.getUrl(), corpus, ex.getClass().getName(), ex.getMessage()});
    8399        }
    84100    }
  • SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/sresult/SearchResultRecordRenderer.java

    r2502 r2527  
    77import eu.clarin.sru.client.fcs.DataViewKWIC;
    88import eu.clarin.sru.client.fcs.Resource;
     9import eu.clarin.sru.fcs.aggregator.data.SearchResult;
    910import java.util.ArrayList;
    1011import java.util.List;
     12import java.util.logging.Level;
    1113import java.util.logging.Logger;
    1214import org.zkoss.zul.Cell;
     
    2123 */
    2224public class SearchResultRecordRenderer implements RowRenderer {
     25   
     26    private SearchResult searchResult;
     27   
     28    private static final Logger logger = Logger.getLogger(SearchResultRecordRenderer.class.getName());
     29   
     30    public SearchResultRecordRenderer(SearchResult searchResult) {
     31        this.searchResult = searchResult;
     32    }
    2333
    2434    @Override
     
    2737        SRURecord record = (SRURecord) data;
    2838
    29         Logger.getLogger(this.getClass().getName()).info(
    30                 String.format("schema = %s, identifier = %s, position = %s",
     39        logger.log(Level.FINE,
     40                "schema = {0}, identifier = {1}, position = {2}",
    3141                new Object[]{record.getRecordSchema(),
    3242                    record.getRecordIdentifier(),
    33                     record.getRecordPosition()}));
     43                    record.getRecordPosition()});
    3444
    3545        if (record.isRecordSchema(ClarinFCSRecordData.RECORD_SCHEMA)) {
    3646            ClarinFCSRecordData rd =
    3747                    (ClarinFCSRecordData) record.getRecordData();
    38 
    39 
    40 
    41 
     48           
    4249            Resource resource = rd.getResource();
    43 
     50           
     51            logger.log(Level.FINE,
     52                "Resource ref={0}, pid={1}, dataViews={2}",
     53                new Object[]{resource.getRef(), resource.getPid(), resource.hasDataViews()});
    4454
    4555//            if (resource.getRef() != null) {
     
    5767            // If dataviews are assigned directly to the resource:                   
    5868            if (resource.hasDataViews()) {
    59                 //zeilen.addAll(dataViews2Rows(resource.getDataViews()));
    6069                appendDataView(row, resource.getDataViews());
    6170            }
     
    6473            if (resource.hasResourceFragments()) {
    6574                for (Resource.ResourceFragment fragment : resource.getResourceFragments()) {
    66                     Logger.getLogger(this.getClass().getName()).info(
    67                             String.format("CLARIN-FCS: ResourceFragment: pid=%s, ref=%s",
    68                             fragment.getPid(), fragment.getRef()));
     75                    logger.log(Level.FINE, "ResourceFragment: ref={0}, pid={1}, dataViews={2}",
     76                            new Object[]{fragment.getRef(), fragment.getPid(), fragment.hasDataViews()});
    6977                    if (fragment.hasDataViews()) {
    70                         //zeilen.addAll(dataViews2Rows(fragment.getDataViews()));
    7178                        appendDataView(row, fragment.getDataViews());
    7279                    }
    7380                }
    74             } //ResourceFragments
     81            }
    7582
    7683        } else if (record.isRecordSchema(SRUSurrogateRecordData.RECORD_SCHEMA)) {
    7784            SRUSurrogateRecordData r =
    7885                    (SRUSurrogateRecordData) record.getRecordData();
    79             Logger.getLogger(this.getClass().getName()).info(
    80                     String.format("SURROGATE DIAGNOSTIC: uri=%s, message=%s, detail=%s",
    81                     r.getURI(), r.getMessage(), r.getDetails()));
     86            logger.log(Level.INFO, "Surrogate diagnostic: uri={0}, message={1}, detail={2}",
     87                    new Object[]{r.getURI(), r.getMessage(), r.getDetails()});
    8288        } else {
    83             Logger.getLogger(this.getClass().getName()).info(
    84                     String.format("UNSUPPORTED SCHEMA: %s",
    85                     record.getRecordSchema()));
     89            logger.log(Level.INFO, "Unsupported schema: {0}", record.getRecordSchema());
    8690        }
    8791
     
    9599            if (dataview.isMimeType(DataViewKWIC.TYPE)) {
    96100                DataViewKWIC kw = (DataViewKWIC) dataview;
    97 
     101                this.searchResult.addKWIC(kw);
    98102
    99103                Label toTheLeft = new Label();
     104                toTheLeft.setValue(kw.getLeft());
     105               
    100106                toTheLeft.setMultiline(true);
    101                 toTheLeft.setValue(kw.getLeft());
    102107                toTheLeft.setSclass("word-wrap");
    103108                Cell toTheLeftCell = new Cell();
     
    106111                toTheLeftCell.setValign("bottom");
    107112                row.appendChild(toTheLeftCell);
    108                 //row.appendChild(toTheLeft);
     113//                row.appendChild(toTheLeft);
    109114               
    110115               
     
    118123                lCell.setValign("bottom");
    119124                row.appendChild(lCell);
    120                 //row.appendChild(l);
     125//                row.appendChild(l);
    121126
    122127                Label toTheRight = new Label();
     128                toTheRight.setValue(kw.getRight());
    123129                toTheRight.setMultiline(true);
    124130                toTheRight.setSclass("word-wrap");
    125                 toTheRight.setValue(kw.getRight());
    126131                Cell toTheRightCell = new Cell();
    127132                toTheRightCell.appendChild(toTheRight);
    128133                toTheRightCell.setValign("bottom");
    129134                row.appendChild(toTheRightCell);
    130                 //row.appendChild(toTheRight);
     135//                row.appendChild(toTheRight);
    131136
    132137            }
  • SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/sresult/SearchResultsController.java

    r2502 r2527  
    99import eu.clarin.sru.client.fcs.ClarinFCSRecordData;
    1010import eu.clarin.sru.client.fcs.ClarinFCSRecordParser;
     11import eu.clarin.sru.client.fcs.DataViewKWIC;
     12import eu.clarin.sru.fcs.aggregator.app.WebAppListener;
    1113import eu.clarin.sru.fcs.aggregator.data.Institution;
    1214import eu.clarin.sru.fcs.aggregator.data.SearchResult;
    1315import eu.clarin.sru.fcs.aggregator.sparam.CorpusTreeNodeRenderer;
     16import eu.clarin.weblicht.wlfxb.io.WLDObjector;
     17import eu.clarin.weblicht.wlfxb.io.WLFormatException;
     18import eu.clarin.weblicht.wlfxb.md.xb.MetaData;
     19import eu.clarin.weblicht.wlfxb.tc.xb.TextCorpusStored;
     20import eu.clarin.weblicht.wlfxb.xb.WLData;
     21import java.io.ByteArrayOutputStream;
    1422import java.util.ArrayList;
    1523import java.util.List;
     
    1826import java.util.logging.Level;
    1927import java.util.logging.Logger;
     28import org.zkoss.zhtml.Filedownload;
    2029import org.zkoss.zk.ui.Component;
    2130import org.zkoss.zk.ui.Executions;
     
    2837import org.zkoss.zul.Label;
    2938import org.zkoss.zul.ListModel;
     39import org.zkoss.zul.Menuitem;
    3040import org.zkoss.zul.Messagebox;
    3141import org.zkoss.zul.SimpleListModel;
     
    4050public class SearchResultsController {
    4151
    42     private static final Logger logger = Logger.getLogger("FCS-AGGREGATOR");
    4352    private List<SearchResult> resultsUnprocessed;
    4453    private List<SearchResult> resultsProcessed;
     
    4756    private UpdateResultsThread resultsThread;
    4857    private int currentRequestId = 0;
    49 
    50     public SearchResultsController(Component resultsArea) {
     58    private Label progress;
     59   
     60    private static final Logger logger = Logger.getLogger(SearchResultsController.class.getName());
     61
     62    public SearchResultsController(Component resultsArea, Label progress) {
    5163        this.resultsArea = resultsArea;
     64        this.progress = progress;
    5265        Executions.getCurrent().getDesktop().enableServerPush(true);
    53     }
    54 
    55     public void executeSearch(Set<Treeitem> selectedItems, int maxRecords, String searchString) {
     66        searchClient = (SRUThreadedClient) Executions.getCurrent().getDesktop().getWebApp().getAttribute(WebAppListener.SHARED_SRU_CLIENT);
     67    }
     68
     69    public void executeSearch(Set<Treeitem> selectedItems, int maxRecords, String searchString, SRUVersion version) {
    5670
    5771        // execute search only if a user selected at least one endpint/corpus
     
    7286        currentRequestId++;
    7387
    74         // initialize client
    75         searchClient = new SRUThreadedClient(SRUVersion.VERSION_1_2);
    76         try {
    77             searchClient.registerRecordParser(new ClarinFCSRecordParser());
    78         } catch (SRUClientException e) {
    79             logger.log(Level.SEVERE, "SRU Client parser registration failed", e);
    80             //TODO error page...
    81         }
    82 
    8388        // clear are where results are to be displayed
    8489        resultsArea.getChildren().clear();
     
    9095        // finally, send search requests to all the selected by user
    9196        // endpoints/corpora and process the responses
    92         sendRequests(selectedItems, maxRecords, searchString);
     97        sendRequests(selectedItems, maxRecords, searchString, version);
    9398        processResponses();
    9499    }
    95100
    96     private void sendRequests(Set<Treeitem> selectedItems, int maxRecords, String searchString) {
    97 
     101    private void sendRequests(Set<Treeitem> selectedItems, int maxRecords, String searchString, SRUVersion version) {
     102
     103        logger.log(Level.INFO, "Executing query={0} maxRecords={1}",
     104                new Object[]{searchString, maxRecords});
     105       
    98106        for (Treeitem selectedItem : selectedItems) {
    99107            Object nodeData = selectedItem.getAttribute(CorpusTreeNodeRenderer.ITEM_DATA);
     
    102110                // if there whole parent corpus/endpoint will be queried
    103111            } else {
    104                 SearchResult resultsItem = executeRequest(nodeData, searchString, maxRecords);
     112                SearchResult resultsItem = executeRequest(nodeData, searchString, maxRecords, version);
    105113                resultsUnprocessed.add(resultsItem);
    106114            }
     
    108116    }
    109117
    110     private SearchResult executeRequest(Object nodeData, String searchString, int maxRecords) {
     118    private SearchResult executeRequest(Object nodeData, String searchString, int maxRecords, SRUVersion version) {
    111119
    112120        SearchResult resultsItem = new SearchResult(nodeData);
    113         //Logger.getLogger("FCS-AGGREGATOR").info("Now executing search: " + searchString + " " + endpoint.getUrl() + " " + corpus.getValue() + " " + maxRecords);
     121        logger.log(Level.FINE, "Executing search for {0} query={1} maxRecords={2}",
     122                new Object[]{nodeData.toString(), searchString, maxRecords});
    114123        SRUSearchRetrieveRequest searchRequest = new SRUSearchRetrieveRequest(resultsItem.getEndpoint().getUrl());
     124        searchRequest.setVersion(version);
    115125        searchRequest.setMaximumRecords(maxRecords);
    116126        searchRequest.setRecordSchema(ClarinFCSRecordData.RECORD_SCHEMA);
     
    123133            resultsItem.setFutureResponse(futureResponse);
    124134        } catch (SRUClientException ex) {
    125             Logger.getLogger(SearchResultsController.class.getName()).log(Level.INFO, resultsItem.getEndpoint().getUrl(), ex);
     135            logger.log(Level.SEVERE, "SearchRetrieve failed for {0}\n {1}\n {2}",
     136                    new String[]{resultsItem.getEndpoint().getUrl(), ex.getClass().getName(), ex.getMessage()});
    126137        }
    127138        return resultsItem;
     
    130141
    131142    private void processResponses() {
    132         processResponsesAsync();
    133         //processResponsesSync();
    134 
    135     }
    136 
    137     private void processResponsesSync() {
    138 
    139         while (!resultsUnprocessed.isEmpty()) {
    140             SearchResult resultsItem = resultsUnprocessed.remove(0);
    141             if (!resultsItem.isWaitingForResponse()) {
    142                 resultsItem.consumeResponse();
    143                 // create groupbox with search results item
    144                 Groupbox groupbox = createRecordsGroup(resultsItem);
    145                 // appand this search result only
    146                 resultsArea.appendChild(groupbox);
    147                 resultsProcessed.add(resultsItem);
    148             } else {
    149                 resultsUnprocessed.add(resultsItem);
    150             }
    151 
    152         }
    153     }
    154 
    155     private void processResponsesAsync() {
     143        processResponsesWithAsyncResultsWindowUpdate();
     144        //processResponsesWithSyncResultsWindowUpdate();
     145
     146    }
     147
     148//    private void processResponsesWithSyncResultsWindowUpdate() {
     149//
     150//        while (!resultsUnprocessed.isEmpty()) {
     151//            SearchResult resultsItem = resultsUnprocessed.remove(0);
     152//            if (!resultsItem.isWaitingForResponse()) {
     153//                resultsItem.consumeResponse();
     154//                // create groupbox with search results item
     155//                Groupbox groupbox = createRecordsGroup(resultsItem);
     156//                // appand this search result only
     157//                resultsArea.appendChild(groupbox);
     158//                resultsProcessed.add(resultsItem);
     159//            } else {
     160//                resultsUnprocessed.add(resultsItem);
     161//            }
     162//
     163//        }
     164//    }
     165   
     166    private void processResponsesWithAsyncResultsWindowUpdate() {
    156167        resultsThread = new UpdateResultsThread();
    157168        resultsThread.start();
     
    163174        public void run() {
    164175            while (!resultsUnprocessed.isEmpty() && !Thread.currentThread().isInterrupted()) {
    165                 //TODO display progress bar...
     176               
    166177                SearchResult resultsItem = resultsUnprocessed.remove(0);
    167178                if (!resultsItem.isWaitingForResponse()) {
     
    182193                    resultsProcessed.add(resultsItem);
    183194                    //System.out.println("RECORDS ITEM ADDED");
     195                   
    184196                } else {
    185197                    resultsUnprocessed.add(resultsItem);
     
    222234            if (requestId != currentRequestId) {
    223235                groupbox.detach();
     236            }
     237           
     238            if (resultsUnprocessed.isEmpty()) {
     239                progress.setValue("");
     240            } else {
     241                progress.setValue("waiting for " + resultsUnprocessed.size() + " responses...");
    224242            }
    225243
     
    269287            //c.setLabel("Left");
    270288            columns.appendChild(c);
     289            //c.setHflex("2");
    271290            c = new Column();
    272291            //c.setLabel("Hit");
    273292            c.setHflex("min");
     293            //c.setHflex("1");
    274294            columns.appendChild(c);
    275295            c = new Column();
     296            //c.setHflex("2");
    276297            //c.setLabel("Right");
    277298            columns.appendChild(c);
    278299            grid.appendChild(columns);
    279            
     300
    280301            List<SRURecord> sruRecords = resultsItem.getResponse().getRecords();
    281302            ListModel lmodel = new SimpleListModel(sruRecords);
    282303            grid.setModel(lmodel);
    283             grid.setRowRenderer(new SearchResultRecordRenderer());
     304            grid.setRowRenderer(new SearchResultRecordRenderer(resultsItem));
    284305            recordsGroup.appendChild(grid);
    285306        } else { // the response was fine, but there are no records
     
    290311    }
    291312
     313    public void exportCSV() {
     314
     315        boolean noResult = true;
     316        StringBuilder csv = new StringBuilder();
     317        if (resultsProcessed != null && !resultsProcessed.isEmpty()) {
     318            for (SearchResult result : resultsProcessed) {
     319                for (DataViewKWIC kwic : result.getDataKWIC()) {
     320                    csv.append("\"");
     321                    csv.append(kwic.getLeft().replace("\"", "QUOTE"));
     322                    csv.append("\"");
     323                    csv.append(",");
     324                    csv.append("\"");
     325                    csv.append(kwic.getKeyword().replace("\"", "QUOTE"));
     326                    csv.append("\"");
     327                    csv.append(",");
     328                    csv.append("\"");
     329                    csv.append(kwic.getRight().replace("\"", "QUOTE"));
     330                    csv.append("\"");
     331                    csv.append("\n");
     332                    noResult = false;
     333                }
     334            }
     335        }
     336
     337        if (noResult) {
     338            Messagebox.show("Nothing to export!");
     339        } else {
     340            Filedownload.save(csv.toString(), "text/plain", "ClarinDFederatedContentSearch.csv");
     341        }
     342    }
     343
     344    public void exportTCF() {
     345
     346        boolean noResult = true;
     347        StringBuilder text = new StringBuilder();
     348
     349        if (resultsProcessed != null && !resultsProcessed.isEmpty()) {
     350            for (SearchResult result : resultsProcessed) {
     351                for (DataViewKWIC kwic : result.getDataKWIC()) {
     352                    text.append(kwic.getLeft());
     353                    text.append(" ");
     354                    text.append(kwic.getKeyword());
     355                    text.append(" ");
     356                    text.append(kwic.getRight());
     357                    text.append("\n");
     358                    noResult = false;
     359                }
     360            }
     361
     362        }
     363
     364        if (noResult) {
     365            Messagebox.show("Nothing to export!");
     366        } else {
     367            WLData data;
     368            MetaData md = new MetaData();
     369            //data.metaData.source = "Tuebingen Uni";
     370            //md.addMetaDataItem("title", "binding test");
     371            //md.addMetaDataItem("author", "Yana");
     372            TextCorpusStored tc = new TextCorpusStored("unknown");
     373            tc.createTextLayer().addText(text.toString());
     374            data = new WLData(md, tc);
     375            ByteArrayOutputStream os = new ByteArrayOutputStream();
     376            try {
     377                WLDObjector.write(data, os);
     378                Filedownload.save(os.toByteArray(), "text/tcf+xml", "ClarinDFederatedContentSearch.xml");
     379            } catch (WLFormatException ex) {
     380                logger.log(Level.SEVERE, "Error exporting TCF {0}\n {1}", new String[]{ex.getClass().getName(), ex.getMessage()});
     381                Messagebox.show("Sorry, export error!");
     382            }
     383        }
     384    }
     385
    292386    public void shutdown() {
    293387        terminateProcessingRequestsAndResponses();
     
    295389
    296390    private void terminateProcessingRequestsAndResponses() {
    297 
    298         if (searchClient != null) {
    299             searchClient.shutdown();
    300         }
    301391
    302392        if (resultsThread != null) {
     
    308398            }
    309399        }
     400
    310401        Logger.getLogger(SearchResultsController.class.getName()).log(Level.INFO, "Search terminated");
    311402    }
  • SRUAggregator/trunk/src/main/webapp/WEB-INF/zk.xml

    r2502 r2527  
    1515    </listener>
    1616    <listener>
    17         <description>WebAppCleanup cleanup</description>
    18         <listener-class>eu.clarin.sru.fcs.aggregator.app.WebAppDestroyedListener</listener-class>
     17        <description>WebApp initialization and cleanup</description>
     18        <listener-class>eu.clarin.sru.fcs.aggregator.app.WebAppListener</listener-class>
    1919    </listener>
    2020   
  • SRUAggregator/trunk/src/main/webapp/index.zul

    r2502 r2527  
    11<?xml version="1.0" encoding="utf-8"?>
    22<?page title="CLARIN-D Federated Content Search"?>
    3 <zk title="CLARIN-D Federated Content Search">
    4 
     3<zk>
    54    <window id="mainWindow" contentStyle="background:white;" height="100%"
    65        apply="eu.clarin.sru.fcs.aggregator.app.Aggregator">
     
    2019                        <hlayout
    2120                            style="margin-top:20px;margin-bottom:10px;margin-left:auto;margin-right:auto;width:95%;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;">
    22                             <textbox hflex="1" id="searchString" value="" focus="true"
     21                            <textbox hflex="1" id="searchString" value="Elefant" focus="true"
    2322                                style="font-size:16px;margin:5px 0px 5px 10px;color:#0e4071;border: 1px solid #801418;"/>
    2423
     
    163162                        <panel>
    164163                            <panelchildren id="resultsPanel" style="overflow: auto">
    165 
    166164                                <window id="resultsBox" style="overflow:auto;">
    167165                                    <iframe src="help.html" width="800px" height="400px"/>
    168166                                </window>
     167                                <label value=" " id="searchResultsProgress" style="border-width:0px;margin-left:5px;"/>
    169168                            </panelchildren>
    170169                        </panel>
Note: See TracChangeset for help on using the changeset viewer.