I'm writing a wicket project for a social network.In my project i have authentication so when a user enter address of the home page he is redirected to login page in this way:
public class MyApplication extends WebApplication {
private Folder uploadFolder = null;
#Override
public Class getHomePage() {
return UserHome.class;
}
public Folder getUploadFolder()
{
return uploadFolder;
}
#Override
protected void init() {
super.init();
// Disable the Ajax debug label!
//getDebugSettings().setAjaxDebugModeEnabled(false);
this.getMarkupSettings().setDefaultMarkupEncoding("UTF-8");
this.getRequestCycleSettings().setResponseRequestEncoding("UTF-8");
mountBookmarkablePage("/BossPage", BossPage.class);
mountBookmarkablePage("/Branch", EditProfile.class);
mountBookmarkablePage("/SA", SuperAdmin.class);
mountBookmarkablePage("/Admin", ir.pnusn.branch.ui.pages.administratorPages.EditProfile.class);
mountBookmarkablePage("/Student", StudentSignUP.class);
mountBookmarkablePage("/Student/Test", StudentSignUpConfirm.class);
mountBookmarkablePage("/Branch/categories.xml", CategoriesXML.class);
get().getPageSettings().setAutomaticMultiWindowSupport(true);
getResourceSettings().setThrowExceptionOnMissingResource(false);
uploadFolder = new Folder("C:\\", "wicket-uploads");
uploadFolder.mkdirs();
this.getSecuritySettings().setAuthorizationStrategy(WiaAuthorizationStrategy.getInstance());
this.getSecuritySettings().setUnauthorizedComponentInstantiationListener(WiaAuthorizationStrategy.getInstance());
addComponentInstantiationListener(new IComponentInstantiationListener() {
public void onInstantiation(final Component component) {
if (!getSecuritySettings().getAuthorizationStrategy().isInstantiationAuthorized(component.getClass())) {
try {
getSecuritySettings().getUnauthorizedComponentInstantiationListener().onUnauthorizedInstantiation(component);
} catch (Exception e) {
System.out.println("ERRORRRRRRR:" + e.toString());
}
}
}
});
}
}
and my WiaAuthorizationStrategy class is like this which will get page names and user roles from a xml file by name Realm.xml :
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package ir.pnusn.ui.library;
import ir.pnusn.authentication.RealmPolicy;
import ir.pnusn.authentication.ui.pages.Login;
import org.apache.wicket.Component;
import org.apache.wicket.RestartResponseAtInterceptPageException;
import org.apache.wicket.authorization.Action;
import org.apache.wicket.authorization.IAuthorizationStrategy;
import org.apache.wicket.authorization.IUnauthorizedComponentInstantiationListener;
public final class WiaAuthorizationStrategy implements
IAuthorizationStrategy,
IUnauthorizedComponentInstantiationListener {
private RealmPolicy roleManager;
private static WiaAuthorizationStrategy instance;
private WiaAuthorizationStrategy() {
roleManager = RealmPolicy.getInstance();
}
public static WiaAuthorizationStrategy getInstance() {
if(instance == null)
instance = new WiaAuthorizationStrategy();
return instance;
}
public boolean isInstantiationAuthorized(Class componentClass) {
if (ProtectedPage.class.isAssignableFrom(componentClass)) {
if (WiaSession.get().getUser() == null) {
return false;
}
if(!roleManager.isAuthorized(WiaSession.get().getUser().getRole(), componentClass.getName()))//WiaSession.get().isAuthenticated();
{
WiaSession.get().setAccess(false);
return false;
}
else
return true;
}
return true;
}
public void onUnauthorizedInstantiation(Component component) {
throw new RestartResponseAtInterceptPageException(
Login.class);
}
public boolean isActionAuthorized(Component component, Action action) {
//System.out.println("Name:" + component.getClass().getName() + "\n Action:" + action.getName() + "\nUser:" + WiaSession.get().getUser());
if (action.equals(Component.RENDER)) {
if (roleManager.containClass(component.getClass().getName()))
{
if (WiaSession.get().getUser() != null) {
if(!roleManager.isAuthorized(WiaSession.get().getUser().getRole(), component.getClass().getName()))
{
WiaSession.get().setAccess(false);
return false;
}
return true;
}
return false;
}
}
return true;
}
}
in this situation i have a googlemap in one of my protectedpage and because googlemap needs to read data for loading builing from a xml so i create a servlet which will create it dynamicly depending on the Username. this servlet is below:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package ir.pnusn.branch.ui.pages;
import ir.pnusn.branch.database.BranchNotFoundException;
import ir.pnusn.branch.database.DatabaseException;
import ir.pnusn.branch.facade.admin.branchDataEnter.BranchDataSubmitFacade;
import ir.pnusn.branch.facade.admin.branchDataEnter.BuildingBean;
import java.util.Iterator;
import java.util.List;
import org.apache.wicket.PageParameters;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.markup.html.WebPage;
/**
*
* #author mohammad
*/
public class CategoriesXML extends WebPage
{
public CategoriesXML(PageParameters parameters)
{
System.out.println("user " + parameters.getString("user"));
StringBuilder builder = new StringBuilder("<markers>");
List<BuildingBean> buildings;
try
{
buildings = BranchDataSubmitFacade.createBranchDataSubmitFacade(parameters.getString("user")).getBranchSecondPageData();
for (Iterator<BuildingBean> it = buildings.iterator(); it.hasNext();)
{
BuildingBean buildingBean = it.next();
builder.append("<marker lat=\"");
builder.append(buildingBean.getLatit());
builder.append("\" lng=\"");
builder.append(buildingBean.getLongit());
builder.append("\"");
builder.append(" address=\"");
builder.append(buildingBean.getDesctiption());
builder.append("\" category=\"branch\" name=\"");
builder.append(buildingBean.getBuildingName());
builder.append("\"/>");
}
builder.append("</markers>");
}
catch (DatabaseException ex)
{
builder = new StringBuilder("<markers></markers>");
}
catch (BranchNotFoundException ex)
{
builder = new StringBuilder("<markers></markers>");
}
RequestCycle.get().getResponse().println(builder.toString());
/*"<markers>" +
"<marker lat=\"35.69187\" lng=\"51.413269\" address=\"Some stuff to display in the First Info Window\" category=\"branch\" name=\"gholi\"/>" +
"<marker lat=\"52.91892\" lng=\"78.89231\" address=\"Some stuff to display in the Second Info Window\" category=\"branch\" name=\"taghi\"/>" +
"<marker lat=\"40.82589\" lng=\"35.10040\" address=\"Some stuff to display in the Third Info Window\" category=\"branch\" name=\"naghi\"/>" +
"</markers> "**/
}
}
I have made this page at first protected and so the user had to loged in to have access this xml but after lot's of debuging i found that googlemap can't log in my system so instead of parsing the dataxml it pars login page html az input. so i changed the extention of the CategoriesXML to extend WebPage.
But now I have another problem:
When i go to the google map page in my Social site I can Not refresh the page because It expires and so I cannot add another building to my data xml.
what should I do?
tell me if you need more code or information
In trying to close this question, which the OP seems to have pretty much abandoned, I'll just post my old comment as an answer..:
In your CategoriesXML I would highly advise against building and adding your tags as Strings and adding them to pages just like that. See if you can work this into a in your .xml(?) file instead, as that's the Wicket way to do things (and as such just might solve the problems you're having)
Would making this WebPage extends org.apache.wicket.Page instead and associate the markup to return as xml instead of html? Basically, mimicking a WebPage, but implementing it for XML.
Related
Somehow I'm not able to build my application in kiosk mode. I'm able to hide status and navigation bar, but not permanent. I want to lock the app and permanently hide the System UI when the app is active without using a 3rd party-app or system setting.
First of all I've tried the NPM packages since they are (sometimes) really helpful and easy to implement. I've tried https://www.npmjs.com/package/react-native-immersive-mode and https://www.npmjs.com/package/react-native-kiosk-mode
They both didn't work since I had to edit the classes. I did followed all the steps and followed them as instructed. Somehow my build always ends in 🤖 Android build failed: Gradle build failed with unknown error. See logs for the "Run gradlew" phase for more information.
I have to be honest, I'm not sure how to find the logs...
I'm using Expo to create, test and build my applications. Would be even greater if I can test kiosk mode in expo go. For now; my app is almost a default initialization when creating a project. Since I first want to create the kiosk functionality without my own code, to make sure there is no error in the actual code.
Currrently my MainApplication.java is default, whenever I add something the build always ends in the same error 🤖 Android build failed: Gradle build failed with unknown error. See logs for the "Run gradlew" phase for more information.:
package com.lavacode.BlocksLauncher;
import android.os.Build;
import android.os.Bundle;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import expo.modules.ReactActivityDelegateWrapper;
public class MainActivity extends ReactActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// Set the theme to AppTheme BEFORE onCreate to support
// coloring the background, status bar, and navigation bar.
// This is required for expo-splash-screen.
setTheme(R.style.AppTheme);
super.onCreate(null);
}
/**
* Returns the name of the main component registered from JavaScript.
* This is used to schedule rendering of the component.
*/
#Override
protected String getMainComponentName() {
return "main";
}
/**
* Returns the instance of the {#link ReactActivityDelegate}. There the RootView is created and
* you can specify the renderer you wish to use - the new renderer (Fabric) or the old renderer
* (Paper).
*/
#Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegateWrapper(this, BuildConfig.IS_NEW_ARCHITECTURE_ENABLED,
new MainActivityDelegate(this, getMainComponentName())
);
}
/**
* Align the back button behavior with Android S
* where moving root activities to background instead of finishing activities.
* #see onBackPressed
*/
#Override
public void invokeDefaultOnBackPressed() {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
if (!moveTaskToBack(false)) {
// For non-root activities, use the default implementation to finish them.
super.invokeDefaultOnBackPressed();
}
return;
}
// Use the default back button implementation on Android S
// because it's doing more than {#link Activity#moveTaskToBack} in fact.
super.invokeDefaultOnBackPressed();
}
public static class MainActivityDelegate extends ReactActivityDelegate {
public MainActivityDelegate(ReactActivity activity, String mainComponentName) {
super(activity, mainComponentName);
}
#Override
protected ReactRootView createRootView() {
ReactRootView reactRootView = new ReactRootView(getContext());
// If you opted-in for the New Architecture, we enable the Fabric Renderer.
reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED);
return reactRootView;
}
#Override
protected boolean isConcurrentRootEnabled() {
// If you opted-in for the New Architecture, we enable Concurrent Root (i.e. React 18).
// More on this on https://reactjs.org/blog/2022/03/29/react-v18.html
return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
}
}
}
MainApplication.java
package com.lavacode.BlocksLauncher;
import android.app.Application;
import android.content.Context;
import android.content.res.Configuration;
import androidx.annotation.NonNull;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.soloader.SoLoader;
import com.lavacode.BlocksLauncher.newarchitecture.MainApplicationReactNativeHost;
import expo.modules.ApplicationLifecycleDispatcher;
import expo.modules.ReactNativeHostWrapper;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHostWrapper(
this,
new ReactNativeHost(this) {
#Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
#Override
protected List<ReactPackage> getPackages() {
#SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
return packages;
}
#Override
protected String getJSMainModuleName() {
return "index";
}
});
private final ReactNativeHost mNewArchitectureNativeHost =
new ReactNativeHostWrapper(this, new MainApplicationReactNativeHost(this));
#Override
public ReactNativeHost getReactNativeHost() {
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
return mNewArchitectureNativeHost;
} else {
return mReactNativeHost;
}
}
#Override
public void onCreate() {
super.onCreate();
// If you opted-in for the New Architecture, we enable the TurboModule system
ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
ApplicationLifecycleDispatcher.onApplicationCreate(this);
}
#Override
public void onConfigurationChanged(#NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig);
}
/**
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
*
* #param context
* #param reactInstanceManager
*/
private static void initializeFlipper(
Context context, ReactInstanceManager reactInstanceManager) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("com.lavacode.BlocksLauncher.ReactNativeFlipper");
aClass
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
.invoke(null, context, reactInstanceManager);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
And my app.json where I did manage to hide the bars as best as possible
{
"expo": {
"name": "BlocksLauncher",
"slug": "BlocksLauncher",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"userInterfaceStyle": "light",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.lavacode.BlocksLauncher"
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#FFFFFF"
},
"package": "com.lavacode.BlocksLauncher"
},
"web": {
"favicon": "./assets/favicon.png"
},
"extra": {
"eas": {
"projectId": "-"
}
},
"androidNavigationBar": {
"visible": "sticky-immersive"
}
}
}
Are there any tips to achieve this? I've been reading a lot about this subject a couple of days already, so I did researched a lot.
I'm pretty new to Java. I'm using Swing and Netbeans on MySQL DB. I am working on a desktop application that allows users to make orders for products. The user have to sign in to order. How do I save the order information for each user after they have logged in. My login code is as shown.
Database connection (dbconnect.java)
package dbconnect;
import java.sql.Connection;
import java.sql.DriverManager;
import javax.swing.JOptionPane;
/**
*
* #author Nipun Senarath
*/
public class dbconnect {
public static Connection connect()
{
Connection sos = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
sos = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/restaurant","root","");
} catch (Exception e)
{
JOptionPane.showMessageDialog(null, e);
}
return sos;
}
public static Connection Connect() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
The login page
PatronLogin.java
package patron.auth;
import dbconnect.dbconnect;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import patron.main.MainClass;
public class PatronLogin extends javax.swing.JFrame {
public PatronLogin() {
initComponents();
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here: Login button
String uname = jTextField1.getText();
String pword = jPasswordField1.getText();
if (uname.equals("")||pword.equals("")) {
JOptionPane.showMessageDialog(rootPane, "Some fields are empty", "Error", 1);
} else {
try {
Connection con = dbconnect.connect();
PreparedStatement pst = con.prepareStatement("select * from patron where username=? and password=?");
pst.setString(1, uname);
pst.setString(2, pword);
ResultSet rs = pst.executeQuery();
if (rs.next()) {
MainClass pt = new MainClass();
pt.setVisible(true);
dispose();
} else {
JOptionPane.showMessageDialog(rootPane, "Username or Password do not match record", "Login error", 1);
}
} catch (Exception ex) {
System.out.println(""+ex);
}
}
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
PatronLogin ln = new PatronLogin();
ln.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
ln.setVisible(true);
}
});
}
Then the user account page
package patron.main;
import patron.event.EventMenuSelected;
import patron.form.Form_1;
import patron.form.Form_4;
import patron.form.Form_3;
import patron.form.Form_2;
import patron.form.Form_Home;
import java.awt.Color;
import javax.swing.JComponent;
public class MainClass extends javax.swing.JFrame {
/**
* Creates new form MainClass
*/
private Form_Home home;
private Form_1 form1;
private Form_2 form2;
public static Form_3 form3;
private Form_4 form4;
public MainClass() {
initComponents();
setBackground(new Color(0, 0, 0, 0));
home = new Form_Home();
form1 = new Form_1();
form2 = new Form_2();
form3 = new Form_3();
form4 = new Form_4();
menu.initMoving(MainClass.this);
menu.addEventMenuSelected(new EventMenuSelected() {
#Override
public void selected(int index) {
if (index == 0) {
setForm(home);
} else if (index == 1) {
setForm(form1);
} else if (index == 2) {
setForm(form2);
} else if (index == 3) {
setForm(form3);
} else if (index == 4) {
setForm(form4);
}
}
});
// set when system open start with home form
setForm(new Form_Home());
}
public void setForm(JComponent com) {
mainPanel.removeAll();
mainPanel.add(com);
mainPanel.repaint();
mainPanel.revalidate();
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MainClass().setVisible(true);
}
});
}
I want to insert an order into the order table with order_id, item, price, and patron_id for the logged in user, so I can be able to retieve it in another table showing the particular user's order history, how do I achieve that. Same goes for other patrons...
There's a lot of work to do, but you can "offload" a lot of that. ;-)
If your desktop-application is a "single-user" application you can create a "Singleton" object to store the current logged user.
That object will represent a "Session", that will be built after a successful login and it will contain the logged user (aka Principal).
There'are various points where you can improve:
security: password are stored in plain text, it would be better to use an hash function for that -- https://www.baeldung.com/java-password-hashing
logic and db code in UI: mixing all the code together will make it very harder to handle it and fix it (believe me). Again, following an Object-Oriented approach is better to model with something like:
interface Products {
List<Product> listAll();
}
interface Orders {
void save(Order order)
}
The implementation of that interfaces will interact with the db, returning the data to the UI and doing the actions started from the user.
db connections handling: obtaining a db connection takes a lot of time, for this reason exists Connection Pools see - https://github.com/brettwooldridge/HikariCP
db interaction way: instead of plain jdbc you're using see -- https://www.marcobehler.com/guides/java-databases
TIPS: Nebeans historically could create interface that interact with standard DB interaction ways (ie JPA) -- https://netbeans.apache.org/tutorials/74/nbm-crud.html
I have a sub-method that builds my FtpInboundFileSynchronizer object. (from a factory object generated out of scope)
private FtpInboundFileSynchronizer createFtpInboundFileSynchronizer(SessionFactory<FTPFile> factory) {
var synchronizer = new FtpInboundFileSynchronizer(factory);
CompositeFileListFilter filter = new CompositeFileListFilter<>();
filter.addFilter(new FtpSimplePatternFileListFilter("filename1.txt"));
filter.addFilter(new FtpSimplePatternFileListFilter("filename2.txt"));
synchronizer.setFilter(filter);
synchronizer.setRemoteDirectory(ftpConfiguration.getPath());
synchronizer.setDeleteRemoteFiles(false);
return synchronizer;
}
However, in this case, I get no files. If I remove one of the FTPSimplePAtternFileListFilter instances, it correctly retrieves that one filename from the FTP server.
The aim is to only download a predefined list of full file names, so both name and extension.
I cannot seem to wrap my head around how to do this. Anyone able to help?
import java.util.Arrays;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.integration.file.filters.AbstractDirectoryAwareFileListFilter;
import org.springframework.util.AntPathMatcher;
/**
* Filter to accept specific file name list.
*/
public class MultiPatternFileListFilter extends AbstractDirectoryAwareFileListFilter<FTPFile> {
private final AntPathMatcher matcher = new AntPathMatcher();
private String[] patterns;
public MultiPatternFileListFilter(String... patterns) {
this.patterns = patterns;
}
#Override
public boolean accept(FTPFile file) {
return alwaysAccept(file) || (file != null && this.matchesAnyPattern(file));
}
#Override
protected boolean isDirectory(FTPFile file) {
return false;
}
protected String getFilename(FTPFile file) {
return (file != null) ? file.getName() : null;
}
private boolean matchesAnyPattern(FTPFile file) {
return Arrays.stream(patterns).anyMatch(pattern -> this.matcher.match(pattern, this.getFilename(file)));
}
}
This solved my problem.
I have written my own scanner to go through my JAX-RS resources and print out the method names and paths using jersey-server-1.18.1. The problem is when I migrate my same code to 2.16 (changing the package names from com.sun.* to org.glassfish.*), It just won't work.
Digging deep I found that those required jersey-server classes are no long public. Anyone knows the reason why? And how can I migrate my code below from 1.x to 2.x ? There is literally no documentation on this migration.
All help appreciated! Below is the code with 1.x
import com.wordnik.swagger.annotations.ApiOperation;
import com.sun.jersey.api.model.AbstractResource;
import com.sun.jersey.api.model.AbstractResourceMethod;
import com.sun.jersey.api.model.AbstractSubResourceLocator;
import com.sun.jersey.api.model.AbstractSubResourceMethod;
import com.sun.jersey.server.impl.modelapi.annotation.IntrospectionModeller;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author shivang
*/
public class Apiscanner {
public static void main(String[] args) {
Apiscanner runClass = new Apiscanner();
runClass.xyz();
}
public void xyz() {
AbstractResource resource = IntrospectionModeller.createResource(BaseResource.class);
String uriPrefix = resource.getPath().getValue();
abc(uriPrefix, resource);
}
public void abc(String uriPrefix, AbstractResource resource) {
for (AbstractResourceMethod srm : resource.getResourceMethods()) {
String uri = uriPrefix;
System.out.println(srm.getHttpMethod() + "\t" + uri);
}
for (AbstractSubResourceMethod srm : resource.getSubResourceMethods()) {
String uri = uriPrefix + srm.getPath().getValue();
ApiOperation op = srm.getAnnotation(ApiOperation.class);
System.out.println(srm.getHttpMethod() + "\t" + uri);
}
if (resource.getSubResourceLocators() != null && !resource.getSubResourceLocators().isEmpty()) {
for (AbstractSubResourceLocator subResourceLocator : resource.getSubResourceLocators()) {
ApiOperation op = subResourceLocator.getAnnotation(ApiOperation.class);
AbstractResource childResource = IntrospectionModeller.createResource(op.response());
String path = subResourceLocator.getPath().getValue();
String pathPrefix = uriPrefix + path;
abc(pathPrefix, childResource);
}
}
}
}
The new APIs for Jersey 2.x, can mainly be found in the org.glassfish.jersey.server.model package.
Some equivalents I can think of:
AbstractResource == Resource
IntrospectionModeller.createResource == I believe Resource.from(BaseResource.class)
AbstractResourceMethod == ResourceMethod
resource.getSubResourceMethods() == getChildResources(), which actually just returns a List<Resource>
AbstractSubResourceLocator == Doesn't seem to exist. We would simply check the above child resource to see if it is a locator
for (Resource childResource: resource.getChildResources()) {
if (childResource.getResourceLocator() != null) {
ResourceMethod method = childResource.getResourceLocator();
Class locatorType = method.getInvocable().getRawResponseType();
}
}
You can also use the enum ResourceMethod.JaxrsType.SUB_RESOURCE_LOCATOR to check if it equals the ResourceMethod.getType()
if (resourceMethod.getType()
.equals(ResourceMethod.JaxrsType.SUB_RESOURCE_LOCATOR) {
}
Here's what I was able to come up with, to kind of match what you got.
import com.wordnik.swagger.annotations.ApiOperation;
import org.glassfish.jersey.server.model.Resource;
import org.glassfish.jersey.server.model.ResourceMethod;
public class ApiScanner {
public static void main(String[] args) {
ApiScanner scanner = new ApiScanner();
scanner.xyz();
}
public void xyz() {
Resource resource = Resource.from(BaseResource.class);
abc(resource.getPath(), resource);
}
public void abc(String uriPrefix, Resource resource) {
for (ResourceMethod resourceMethod: resource.getResourceMethods()) {
String uri = uriPrefix;
System.out.println("-- Resource Method --");
System.out.println(resourceMethod.getHttpMethod() + "\t" + uri);
ApiOperation api = resourceMethod.getInvocable().getDefinitionMethod()
.getAnnotation(ApiOperation.class);
}
for (Resource childResource: resource.getChildResources()) {
System.out.println("-- Child Resource --");
System.out.println(childResource.getPath() + "\t" + childResource.getName());
if (childResource.getResourceLocator() != null) {
System.out.println("-- Sub-Resource Locator --");
ResourceMethod method = childResource.getResourceLocator();
Class locatorType = method.getInvocable().getRawResponseType();
System.out.println(locatorType);
Resource subResource = Resource.from(locatorType);
abc(childResource.getPath(), subResource);
}
}
}
}
OK. So I was able to get it to work almost at the same time as #peeskillet provided the answer. I will add just a different flavor of the answer in case people want to reuse the code:
import java.util.ArrayList;
import java.util.List;
import org.glassfish.jersey.server.model.Resource;
import org.glassfish.jersey.server.model.ResourceMethod;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author shivang
*/
public class JerseyResourceScanner {
public static void main(String[] args) {
JerseyResourceScanner runClass = new JerseyResourceScanner();
runClass.scan(BaseResource.class);
}
public void scan(Class baseClass) {
Resource resource = Resource.builder(baseClass).build();
String uriPrefix = "";
process(uriPrefix, resource);
}
private void process(String uriPrefix, Resource resource) {
String pathPrefix = uriPrefix;
List<Resource> resources = new ArrayList<>();
resources.addAll(resource.getChildResources());
if (resource.getPath() != null) {
pathPrefix = pathPrefix + resource.getPath();
}
for (ResourceMethod method : resource.getAllMethods()) {
if (method.getType().equals(ResourceMethod.JaxrsType.SUB_RESOURCE_LOCATOR)) {
resources.add(
Resource.from(resource.getResourceLocator()
.getInvocable().getDefinitionMethod().getReturnType()));
}
else {
System.out.println(method.getHttpMethod() + "\t" + pathPrefix);
}
}
for (Resource childResource : resources) {
process(pathPrefix, childResource);
}
}
}
Is it possible to determine, what client libs have been loaded prior to a component?
We are running multiple site backed by different Javascript frameworks. In order to run a single component across the board, it's not sufficient to just use
<cq:includeClientLib categories="blah"/>
We need to identify the respective framework (i.e. AngularJS, Vanilla, jQuery, blah) in order to facilitate the integration.
We are looking for a decent server side solution.
I haven't actually done this, but it would presumably be possible if you are buffering your output to clone the JspWriter buffer or examine it to see what it already contains. That sounds ugly to me, though. But this is decompiled code for how the cq:includeClientLib tag adds libraries to the output, which may show you how you can read back what was previously written:
package com.adobe.granite.ui.tags;
import com.day.cq.widget.HtmlLibraryManager;
import java.io.IOException;
import javax.servlet.ServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.TagSupport;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.scripting.SlingBindings;
import org.apache.sling.scripting.jsp.util.TagUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class IncludeClientLibraryTag extends TagSupport {
private static final long serialVersionUID = -3068291967085012331L;
private static final Logger log = LoggerFactory.getLogger(IncludeClientLibraryTag.class);
private String categories;
private String js;
private String css;
private String theme;
private Boolean themed;
public IncludeClientLibraryTag() {
}
public void setPageContext(PageContext pageContext) {
super.setPageContext(pageContext);
this.categories = null;
this.js = null;
this.css = null;
this.theme = null;
this.themed = null;
}
public void setCategories(String categories) {
this.categories = categories;
}
public void setJs(String js) {
this.js = js;
}
public void setCss(String css) {
this.css = css;
}
public void setTheme(String theme) {
this.theme = theme;
}
public void setThemed(boolean themed) {
this.themed = Boolean.valueOf(themed);
}
public int doEndTag() throws JspException {
SlingHttpServletRequest request = TagUtil.getRequest(this.pageContext);
HtmlLibraryManager libManager = this.getHtmlLibraryManager(request);
if(libManager == null) {
log.warn("<ui:includeClientLib>: Could not retrieve HtmlLibraryManager service, skipping inclusion.");
return 6;
} else {
JspWriter out = this.pageContext.getOut();
try {
if(this.categories != null) {
libManager.writeIncludes(request, out, toArray(this.categories));
} else if(this.theme != null) {
libManager.writeThemeInclude(request, out, toArray(this.theme));
} else if(this.js != null) {
if(this.themed != null) {
libManager.writeJsInclude(request, out, this.themed.booleanValue(), toArray(this.js));
} else {
libManager.writeJsInclude(request, out, toArray(this.js));
}
} else if(this.css != null) {
if(this.themed != null) {
libManager.writeCssInclude(request, out, this.themed.booleanValue(), toArray(this.css));
} else {
libManager.writeCssInclude(request, out, toArray(this.css));
}
}
return 6;
} catch (IOException var6) {
String libs = this.categories != null?"categories: " + this.categories:(this.theme != null?"theme: " + this.theme:(this.js != null?"js: " + this.js:(this.css != null?"css: " + this.css:"")));
throw new JspException("Could not include client library: " + libs, var6);
}
}
}
private HtmlLibraryManager getHtmlLibraryManager(ServletRequest request) {
SlingBindings bindings = (SlingBindings)request.getAttribute(SlingBindings.class.getName());
return (HtmlLibraryManager)bindings.getSling().getService(HtmlLibraryManager.class);
}
private static String[] toArray(String commaSeparatedList) {
if(commaSeparatedList == null) {
return new String[0];
} else {
String[] split = commaSeparatedList.split(",");
for(int i = 0; i < split.length; ++i) {
split[i] = split[i].trim();
}
return split;
}
}
}
I think the best solution may be to use the client library dependencies or embed attributes in your library, though, or let the client-side JavaScript test if a library is present (ex. test if the jQuery object is undefined) and then take appropriate action. In other words, let the client side determine the final rendering based on what libraries exist on in the client. It sounds like this may not be possible for your situation, though.
dependencies: This is a list of other client library categories on
which this library folder depends. For example, given two
cq:ClientLibraryFolder nodes F and G, if a file in F requires another
file in G in order to function properly, then at least one of the
categories of G should be among the dependencies of F.
embed: Used to > embed code from other libraries. If node F embeds nodes G and H, the
resulting HTML will be a concetration of content from nodes G and H.