1 package org.apache.archiva.redback.struts2.action.admin;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import org.apache.archiva.redback.rbac.RBACManager;
23 import org.apache.archiva.redback.rbac.Resource;
24 import org.apache.commons.beanutils.PropertyUtils;
25 import org.apache.commons.lang.StringEscapeUtils;
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.archiva.redback.struts2.action.AbstractSecurityAction;
28 import org.apache.archiva.redback.system.SecuritySystem;
29 import org.codehaus.plexus.registry.Registry;
30 import org.apache.archiva.redback.integration.interceptor.SecureActionBundle;
31 import org.apache.archiva.redback.integration.interceptor.SecureActionException;
32 import org.apache.archiva.redback.integration.role.RoleConstants;
33 import org.springframework.context.annotation.Scope;
34 import org.springframework.stereotype.Controller;
36 import javax.inject.Inject;
37 import javax.inject.Named;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.Iterator;
41 import java.util.List;
48 * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
51 @Controller( "redback-sysinfo" )
53 public class SystemInfoAction
54 extends AbstractSecurityAction
56 // ------------------------------------------------------------------
57 // Component Requirements
58 // ------------------------------------------------------------------
64 private SecuritySystem securitySystem;
67 * role-hint="commons-configuration"
70 @Named( value = "commons-configuration" )
71 private Registry registry;
77 @Named( value = "rBACManager#cached" )
78 private RBACManager rbacManager;
80 // Class.getClass() and some JPOX classes
81 private static final List<String> ignoredReaders = Arrays.asList( "class", "copy" );
83 private static final String NULL = "<null>";
85 private static final char LN = Character.LINE_SEPARATOR;
87 private static final String INDENT = " ";
89 private static final int MAXDEPTH = 10;
91 // ------------------------------------------------------------------
93 // ------------------------------------------------------------------
95 private StringBuilder details;
97 // ------------------------------------------------------------------
98 // Action Entry Points - (aka Names)
99 // ------------------------------------------------------------------
103 details = new StringBuilder();
105 details.append( "Configuration: " );
106 dumpObject( details, registry, INDENT );
107 details.append( registry.dump() );
108 details.append( LN );
110 details.append( LN ).append( "<hr/>" ).append( LN );
111 details.append( "RBAC Manager: " );
112 dumpObject( details, rbacManager, INDENT );
114 details.append( LN ).append( "<hr/>" ).append( LN );
115 details.append( "SecuritySystem: " );
116 dumpObject( details, securitySystem, INDENT );
121 private void dumpObject( StringBuilder sb, Object obj, String indent )
123 dumpObjectSwitchboard( new ArrayList<Object>(), sb, obj, indent, 0 );
127 * The recursive object dumping switchboard.
129 * @param seenObjects objects already seen (to prevent cycles)
130 * @param sb the stringbuffer to populate
131 * @param obj the object to dump
132 * @param indent the current indent string.
133 * @param depth the depth in the tree.
135 private void dumpObjectSwitchboard( List<Object> seenObjects, StringBuilder sb, Object obj, String indent,
140 sb.append( NULL ).append( LN );
144 if ( depth > MAXDEPTH )
146 sb.append( StringEscapeUtils.escapeHtml( "<MAX DEPTH>" ) );
153 String className = obj.getClass().getName();
155 sb.append( '(' ).append( className ).append( ") " );
157 if ( obj instanceof List )
159 dumpIterator( seenObjects, sb, ( (List<?>) obj ).iterator(), indent, depth );
161 else if ( obj instanceof Set )
163 dumpIterator( seenObjects, sb, ( (Set<?>) obj ).iterator(), indent, depth );
165 else if ( obj instanceof Map )
167 dumpIterator( seenObjects, sb, ( (Map<?, ?>) obj ).entrySet().iterator(), indent, depth );
169 else if ( obj instanceof Iterator )
171 dumpIterator( seenObjects, sb, (Iterator<?>) obj, indent, depth );
175 // Filter classes that start with java or javax
176 if ( className.startsWith( "java." ) || className.startsWith( "javax." ) )
178 sb.append( StringEscapeUtils.escapeHtml( obj.toString() ) ).append( LN );
183 if ( seenObjects.contains( obj ) )
186 sb.append( StringEscapeUtils.escapeHtml( "<seen already preventing cycle in dump> " ) );
191 // Adding object to seen list (to prevent cycles)
192 seenObjects.add( obj );
194 dumpObjectReaders( seenObjects, sb, obj, indent, depth );
199 @SuppressWarnings( "unchecked" )
200 private void dumpObjectReaders( List<Object> seenObjects, StringBuilder sb, Object obj, String indent, int depth )
202 sb.append( obj.toString() ).append( LN );
207 Map<String, Object> readers = PropertyUtils.describe( obj );
208 for ( Map.Entry<String, Object> readerEntry : readers.entrySet() )
210 name = (String) readerEntry.getKey();
212 if ( ignoredReaders.contains( name ) )
219 sb.append( name ).append( ':' );
221 Object value = readerEntry.getValue();
224 sb.append( NULL ).append( LN );
228 dumpObjectSwitchboard( seenObjects, sb, value, INDENT + indent, depth );
232 catch ( Throwable e )
234 sb.append( LN ).append( indent );
235 sb.append( "Unable to read bean [" ).append( obj.getClass().getName() );
236 if ( StringUtils.isNotBlank( name ) )
238 sb.append( ".get" ).append( StringUtils.capitalize( name ) ).append( "()" );
240 sb.append( "]: " ).append( '(' ).append( e.getClass().getName() ).append( ") " );
241 sb.append( e.getMessage() ).append( LN );
245 private void dumpIterator( List<Object> seenObjects, StringBuilder sb, Iterator<?> iterator, String indent,
249 while ( iterator.hasNext() )
251 Object entry = iterator.next();
253 dumpObjectSwitchboard( seenObjects, sb, entry, indent + " | ", depth );
257 // ------------------------------------------------------------------
258 // Parameter Accessor Methods
259 // ------------------------------------------------------------------
261 public String getDetails()
263 return details.toString();
266 public SecureActionBundle initSecureActionBundle()
267 throws SecureActionException
269 SecureActionBundle bundle = new SecureActionBundle();
270 bundle.setRequiresAuthentication( true );
271 bundle.addRequiredAuthorization( RoleConstants.CONFIGURATION_EDIT_OPERATION, Resource.GLOBAL );