Inheritance in Enumerations to provide subsets?
I know that there is no such thing as inheritance in enumerations, but I think it might be useful whenever the developer needs to define a subset relationship.
E.g.:
public enum A {
V1,
V2,
V3,
V4
public enum B extends A {
V1,
V2
Semantically, the developer is saying that B is a subset of A.
This means that the value A.V1 is the same value as B.V1.
A user could pass a B in place of an A, and B would have all the properties of A.
Can anyone think of an argument why this should or should not be in the language?
Personally, I don't see any advantage with your suggestion, compared to the already existing EnumSet class. A couple of disadvantages with your suggestion are:
* It is not obvious that an enum extension is equivalent to a subset. That seems rather arbitrary to me (in fact, I find it counter-intuitive).
* It unnecessarily complicates the language.
Just my 2 cents, of course.
Similar Messages
-
Disable Inheritance on folder - Full permissions unable to rename
I've got a document library with a couple folders inside. One of the folders I've disabled the inheritance of permission and provided a test user full control of the folder. They can add/delete files inside the folder but they're not able to rename the
folder itself, it tells them access is denied. Is this by design? Any way around it?Hi,
Still not able to reproduce so you need to check below points:
1. Check event viewer in case any log entry is there:
2. Also make below changes in web app your web.config file:
Call stack =true and customerror mode = "Off
Let us know if you find anything there
Hemendra: "Yesterday is just a memory,Tomorrow we may never see"
Whenever you see a reply and if you think is helpful, click "Vote As Helpful"! And whenever you see a reply
being an answer to the question of the thread, click "Mark As Answer
Changed both items in the web.config, performed the action again and got access denied. Don't see anything different in the ULS and don't see anything in the event viewer...
You cant duplicate this? Are you attempting it as a farm/site admin? I've got just a regular user (User1) that I assigned full control to a doc library... 3 folders (A,B,C) inside the doc library. Disabled permissions inheritance on folder A and provided
User1 full control. Folder B and C are left alone.
User1 can modify contents inside of Folder A,B and C. Can add and deleted folders, other than A. It can rename the folders B and C, but get access denied on folder A. -
Simple type enumeration access
Hello colleagues,
while creating a data dictionary type, you can define an enumeration with keys and description texts. Additionally you can let the WD generator to create the class representation for this enumeration. So you can use it in your code.
The generated enumeration only provides the key constant value (enum.getName()) but doesn't bring the description text. Is there any "official way" to read it in code providing certain locale?
I know, you can create a context attribute of this simple type and go for the following expression:
wdContext.nodeTableLine().getNodeInfo().getAttribute("attr").getSimpleType().getSVServices().getModifiableSimpleValueSet()
but I can't imagine the WD doesn't provide any context independent way for this simple operation.
Regards
DimitriHi
I donu2019t want to populate the list of the enumeration. The list is defined at design time. I just want to read key descriptions of the enumeration programmatically and I donu2019t want to use the context for that.
To your comment: if you use an input field with an enumerated data dictionary type, only the key of the enumeration will be shown in the field.
Regards
Dimitri -
Error saying "must declare body"
I was debugging a code and I got it to 1 error.
It was missing a main method, so I did static void Main(); in the beginning of the code.
The error says "ffbCS.Program.Main() must declare a body because it is not marked abstract, extern, or partial"
Does the main method always go in the beginning of the code or can it come after some code? Is there other types of main methods? I used static void
Main(); because this is the only one that I know of.
Below is my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.ComponentModel;
using System.Device;
using Microsoft.DirectX;
using Microsoft.DirectX.DirectInput;
namespace ffbCS
class Program
static void Main();
public sealed class DirectInputWrapper
#region ForceType
<summary style="color:#111111;font-family:'Segoe UI', Arial, sans-serif;font-size:14px;line-height:normal;">
/// This enumeration simply provides a shorthand way to reference
/// the custom forces we create -- it's not a base part of DirectX,
/// though, so you can use a completely different method.
///</summary>
public enum ForceType
VeryBriefJolt,
BriefJolt,
LowRumble,
HardRumble
#endregion
//this class lets us send FF commands to up to two game pads,
//but your own class could support as many as you want
private static Device device1;
private static Device device2;
private static Dictionary<forcetype,> P1Forces;
private static Dictionary<forcetype,> P2Forces;
#region Initialize
///<summary style="color:#111111;font-family:'Segoe UI', Arial, sans-serif;font-size:14px;line-height:normal;">
/// Initialize DirectInput
///</summary>
public static void Initialize( System.Windows.Forms.Control Parent )
if ( device1 != null )
device1.Dispose();
device1 = null;
if ( device2 != null )
device2.Dispose();
device2 = null;
foreach ( DeviceInstance instance in Manager.GetDevices( DeviceClass.GameControl,
EnumDevicesFlags.AttachedOnly ) )
if ( device1 == null )
device1 = new Device( instance.InstanceGuid );
else if ( device2 == null )
device2 = new Device( instance.InstanceGuid );
DisposeForces();
P1Forces = new Dictionary<forcetype,>();
P2Forces = new Dictionary<forcetype,>();
InitializeDevice( Parent, device1 );
InitializeDevice( Parent, device2 );
#endregion
#region InitializeDevice
private static void InitializeDevice( System.Windows.Forms.Control Parent, Device Dev )
if ( Dev == null )
return;
Dev.SetDataFormat( DeviceDataFormat.Joystick );
Dev.SetCooperativeLevel( Parent, CooperativeLevelFlags.Background |
CooperativeLevelFlags.Exclusive );
Dev.Properties.AxisModeAbsolute = true;
Dev.Properties.AutoCenter = false;
Dev.Acquire();
int[] axis = null;
// Enumerate any axes
foreach ( DeviceObjectInstance doi in Dev.Objects )
if ( ( doi.ObjectId & (int)DeviceObjectTypeFlags.Axis ) != 0 )
// We found an axis, set the range to a max of 10,000
Dev.Properties.SetRange( ParameterHow.ById,
doi.ObjectId, new InputRange( -5000, 5000 ) );
int[] temp;
// Get info about first two FF axii on the device
if ( ( doi.Flags & (int)ObjectInstanceFlags.Actuator ) != 0 )
if ( axis != null )
temp = new int[axis.Length + 1];
axis.CopyTo( temp, 0 );
axis = temp;
else
axis = new int[1];
// Store the offset of each axis.
axis[axis.Length - 1] = doi.Offset;
if ( axis.Length == 2 )
break;
Dictionary<forcetype,> forces;
if ( Dev == device1 )
forces = P1Forces;
else
forces = P2Forces;
try
if ( axis != null )
forces.Add( ForceType.VeryBriefJolt,
InitializeForce( Dev, EffectType.ConstantForce, axis,
6000, EffectFlags.ObjectOffsets | EffectFlags.Spherical, 150000 ) );
forces.Add( ForceType.BriefJolt,
InitializeForce( Dev, EffectType.ConstantForce, axis,
10000, EffectFlags.ObjectOffsets | EffectFlags.Spherical, 250000 ) );
forces.Add( ForceType.LowRumble,
InitializeForce( Dev, EffectType.ConstantForce, axis,
2000, EffectFlags.ObjectOffsets | EffectFlags.Cartesian, 900000 ) );
forces.Add( ForceType.HardRumble,
InitializeForce( Dev, EffectType.ConstantForce, axis,
10000, EffectFlags.ObjectOffsets | EffectFlags.Spherical, 2000000 ) );
catch ( Exception e )
System.Windows.Forms.MessageBox.Show( "Could not initalize force feedback:\n\n" + e );
#endregion
#region DisposeForces
public static void DisposeForces()
if ( P1Forces != null )
foreach ( EffectObject o in P1Forces.Values )
o.Dispose();
P1Forces = null;
if ( P2Forces != null )
foreach ( EffectObject o in P2Forces.Values )
o.Dispose();
P2Forces = null;
#endregion
#region SendForce
public static void SendForce( ForceType Type, bool IsPlayer1 )
Dictionary<forcetype,> forces;
if ( IsPlayer1 )
forces = P1Forces;
else
forces = P2Forces;
if ( forces == null )
return;
if ( !forces.ContainsKey( Type ) )
return;
EffectObject force = forces[Type];
force.Start( 1 );
#endregion
#region InitializeForce
public static EffectObject InitializeForce( Device Dev, EffectType Type,
int[] Axis, int Magnitude, EffectFlags Flags, int Duration )
EffectObject eo = null;
Effect e;
foreach ( EffectInformation ei in Dev.GetEffects( EffectType.All ) )
if ( DInputHelper.GetTypeCode( ei.EffectType ) == (int)Type )
e = new Effect();
e.SetDirection( new int[Axis.Length] );
e.SetAxes( new int[1] );
//this is the offending line in the Microsoft examples
//setting axes to 2 causes the dreaded "Value does not fall within expected range" error
//this is evidently a bug in Managed DirectX, at least affecting some game pads,
//and this is the only workaround I've found.
//I have not been able to successfully load FFE files in Managed DirectX
//due to this same problem (presumably, in the inner initialization code
//when loading from FFE, it is trying to load two axes there, as well).
//This problem exists with all verys of Managed DirectX, as far as I can tell,
//at least up through March 2008 when this example was written.
e.EffectType = Type;
e.ConditionStruct = new Condition[Axis.Length];
e.Duration = Duration;
e.Gain = 10000;
e.Constant = new ConstantForce();
e.Constant.Magnitude = Magnitude;
e.SamplePeriod = 0;
e.TriggerButton = (int)Microsoft.DirectX.DirectInput.Button.NoTrigger;
e.TriggerRepeatInterval = (int)DI.Infinite;
e.Flags = Flags;
e.UsesEnvelope = false;
// Create the effect, using the passed in guid.
eo = new EffectObject( ei.EffectGuid, e, Dev );
return eo;
#endregionI was debugging a code and I got it to 1 error.
It was missing a main method, so I did static void Main(); in the beginning of the code.
The error says "ffbCS.Program.Main() must declare a body because it is not marked abstract, extern, or partial"
Does the main method always go in the beginning of the code or can it come after some code? Is there other types of main methods? I used static void
Main(); because this is the only one that I know of.
Below is my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.ComponentModel;
using System.Device;
using Microsoft.DirectX;
using Microsoft.DirectX.DirectInput;
namespace ffbCS
class Program
static void Main();
public sealed class DirectInputWrapper
#region ForceType
///<summary style="color:#111111;font-family:'Segoe UI', Arial, sans-serif;font-size:14px;line-height:normal;">
/// This enumeration simply provides a shorthand way to reference
/// the custom forces we create -- it's not a base part of DirectX,
/// though, so you can use a completely different method.
///</summary>
public enum ForceType
VeryBriefJolt,
BriefJolt,
LowRumble,
HardRumble
#endregion
//this class lets us send FF commands to up to two game pads,
//but your own class could support as many as you want
private static Device device1;
private static Device device2;
private static Dictionary<forcetype,> P1Forces;
private static Dictionary<forcetype,> P2Forces;
#region Initialize
///<summary style="color:#111111;font-family:'Segoe UI', Arial, sans-serif;font-size:14px;line-height:normal;">
/// Initialize DirectInput
///</summary>
public static void Initialize( System.Windows.Forms.Control Parent )
if ( device1 != null )
device1.Dispose();
device1 = null;
if ( device2 != null )
device2.Dispose();
device2 = null;
foreach ( DeviceInstance instance in Manager.GetDevices( DeviceClass.GameControl,
EnumDevicesFlags.AttachedOnly ) )
if ( device1 == null )
device1 = new Device( instance.InstanceGuid );
else if ( device2 == null )
device2 = new Device( instance.InstanceGuid );
DisposeForces();
P1Forces = new Dictionary<forcetype,>();
P2Forces = new Dictionary<forcetype,>();
InitializeDevice( Parent, device1 );
InitializeDevice( Parent, device2 );
#endregion
#region InitializeDevice
private static void InitializeDevice( System.Windows.Forms.Control Parent, Device Dev )
if ( Dev == null )
return;
Dev.SetDataFormat( DeviceDataFormat.Joystick );
Dev.SetCooperativeLevel( Parent, CooperativeLevelFlags.Background |
CooperativeLevelFlags.Exclusive );
Dev.Properties.AxisModeAbsolute = true;
Dev.Properties.AutoCenter = false;
Dev.Acquire();
int[] axis = null;
// Enumerate any axes
foreach ( DeviceObjectInstance doi in Dev.Objects )
if ( ( doi.ObjectId & (int)DeviceObjectTypeFlags.Axis ) != 0 )
// We found an axis, set the range to a max of 10,000
Dev.Properties.SetRange( ParameterHow.ById,
doi.ObjectId, new InputRange( -5000, 5000 ) );
int[] temp;
// Get info about first two FF axii on the device
if ( ( doi.Flags & (int)ObjectInstanceFlags.Actuator ) != 0 )
if ( axis != null )
temp = new int[axis.Length + 1];
axis.CopyTo( temp, 0 );
axis = temp;
else
axis = new int[1];
// Store the offset of each axis.
axis[axis.Length - 1] = doi.Offset;
if ( axis.Length == 2 )
break;
Dictionary<forcetype,> forces;
if ( Dev == device1 )
forces = P1Forces;
else
forces = P2Forces;
try
if ( axis != null )
forces.Add( ForceType.VeryBriefJolt,
InitializeForce( Dev, EffectType.ConstantForce, axis,
6000, EffectFlags.ObjectOffsets | EffectFlags.Spherical, 150000 ) );
forces.Add( ForceType.BriefJolt,
InitializeForce( Dev, EffectType.ConstantForce, axis,
10000, EffectFlags.ObjectOffsets | EffectFlags.Spherical, 250000 ) );
forces.Add( ForceType.LowRumble,
InitializeForce( Dev, EffectType.ConstantForce, axis,
2000, EffectFlags.ObjectOffsets | EffectFlags.Cartesian, 900000 ) );
forces.Add( ForceType.HardRumble,
InitializeForce( Dev, EffectType.ConstantForce, axis,
10000, EffectFlags.ObjectOffsets | EffectFlags.Spherical, 2000000 ) );
catch ( Exception e )
System.Windows.Forms.MessageBox.Show( "Could not initalize force feedback:\n\n" + e );
#endregion
#region DisposeForces
public static void DisposeForces()
if ( P1Forces != null )
foreach ( EffectObject o in P1Forces.Values )
o.Dispose();
P1Forces = null;
if ( P2Forces != null )
foreach ( EffectObject o in P2Forces.Values )
o.Dispose();
P2Forces = null;
#endregion
#region SendForce
public static void SendForce( ForceType Type, bool IsPlayer1 )
Dictionary<forcetype,> forces;
if ( IsPlayer1 )
forces = P1Forces;
else
forces = P2Forces;
if ( forces == null )
return;
if ( !forces.ContainsKey( Type ) )
return;
EffectObject force = forces[Type];
force.Start( 1 );
#endregion
#region InitializeForce
public static EffectObject InitializeForce( Device Dev, EffectType Type,
int[] Axis, int Magnitude, EffectFlags Flags, int Duration )
EffectObject eo = null;
Effect e;
foreach ( EffectInformation ei in Dev.GetEffects( EffectType.All ) )
if ( DInputHelper.GetTypeCode( ei.EffectType ) == (int)Type )
e = new Effect();
e.SetDirection( new int[Axis.Length] );
e.SetAxes( new int[1] );
//this is the offending line in the Microsoft examples
//setting axes to 2 causes the dreaded "Value does not fall within expected range" error
//this is evidently a bug in Managed DirectX, at least affecting some game pads,
//and this is the only workaround I've found.
//I have not been able to successfully load FFE files in Managed DirectX
//due to this same problem (presumably, in the inner initialization code
//when loading from FFE, it is trying to load two axes there, as well).
//This problem exists with all verys of Managed DirectX, as far as I can tell,
//at least up through March 2008 when this example was written.
e.EffectType = Type;
e.ConditionStruct = new Condition[Axis.Length];
e.Duration = Duration;
e.Gain = 10000;
e.Constant = new ConstantForce();
e.Constant.Magnitude = Magnitude;
e.SamplePeriod = 0;
e.TriggerButton = (int)Microsoft.DirectX.DirectInput.Button.NoTrigger;
e.TriggerRepeatInterval = (int)DI.Infinite;
e.Flags = Flags;
e.UsesEnvelope = false;
// Create the effect, using the passed in guid.
eo = new EffectObject( ei.EffectGuid, e, Dev );
return eo;
#endregion -
I want to print time stamp every second to an excel sheet, tried 1000 of times to add row to the sheet but failed, any clue how to?
Attachments:
time stamp in a row.vi 67 KBThat's because you're wiring the N value of the for-loop to the "column" element of the cell cluster, and you are wiring a constant of 1 to the "row" element of the cluster. You also have several issues with the code:
Do NOT hard-code a path the way you are doing. What will happen if someone else tries to run this code? What will happen if it runs on another computer that has Windows XP? Use a control and set it to a default value if you want.
No error handling whatsoever.
Do not use integer constants in lieu of enumerations. The VIs you are calling have parameters for which enumerations are provided. Use them. Right-click on the inputs and select Create->Constant. This will create the enumerations for you. They are self-documenting.
Do not have a time delay that cannot be bypassed if there is an error. You are running the loop 500 times. What will happen if there's an error on iteration 20? The loop still has to run 480 times, forcing you to wait 480 seconds before you can stop.
Be aware that timestamps between LabVIEW and Excel are different, since they use different epochs. This has been discussed ad nauseam in these forums, so do a search and you will find out how to deal with this.
See attached modification as a starting point. You should also review the LabVIEW training materials. To learn more about LabVIEW it is recommended that you go through the introduction material, tutorial(s), and other material in the NI Developer Zone's Learning Center which provides links to other materials and other tutorials. There are also several Technical Resources. You can also take the online courses for free.
Attachments:
time stamp in a row MOD.vi 79 KB -
Which is better from performance point of view : Enum or String?
Hello All
While working to re-factor code so as to improve performance,I saw that repeatedly some Strings are used to be put as keys in a HashMap.
Will there be an improvement in performance if I assign use enums in place of using double quoted strings everytime.
Also,Is it a better idea to use string constants rather than enums.
Can anyone help me over this?
Thanks in advance
MansiFound an article in Java performance tuning book.But they nowhere mentioned the perfect reason for doing this.Here's the artice :
Enumerating constants
Another canonicalization technique often used is replacing constant objects with integers. For example, rather than use the strings "female" and "male", you should use a constant defined in an interface:
public interface GENDER
public static final int FEMALE=1;
public static final int MALE=2;
Used consistently, this enumeration can provide both speed and memory advantages. The enumeration requires less memory than the equivalent strings and makes network transfers faster. Comparisons are faster too, as the identity comparison can be used instead of the equality comparison. For example, you can use:
this.gender == FEMALE;
instead of:
this.gender.equals("female"); -
BUG: JDeveloper code editor shows valid static import call as error
I've noticed what appears to be a bug in the JDeveloper code validator when dealing with static imports.
The following classes demonstrate the problem:
package test;
public class Parent {
public static void parentMethod() {
System.out.println("called parentMethod.");
package test;
public class Child extends Parent {
public static void childMethod() {
System.out.println("called childMethod.");
package test;
import static test.Child.*;
public class StaticInheritanceTest {
public static void main(String[] args) {
Child.childMethod();
Child.parentMethod();
childMethod();
parentMethod(); //<-- this line is highlighted as an error
}Notice how on lines 7 and 8 of StaticInheritanceTest, the code validator does recognise that both parentMethod and childMethod are static methods of the Child class.
Since 'Child' has been statically imported, then parentMethod should be available. Although parentMethod is presented as an 'auto-suggest' at line 11 in StaticInheritanceTest, when you try to call it the code editor shows the call as an error and the Ctrl-Click (to drill down into the method) doesn't work.
When I run the class, it compiles successfully and runs with the following output:
called childMethod.
called parentMethod.
called childMethod.
called parentMethod.This might seem like an obscure and theoretical problem, but I've hit this whilst using Mockito, which uses exactly this kind of inherited static method to provide matchers.Hi,
thanks. Will file a bug. This seems to be a designtime only issue that does not present a show stopper.
Frank -
Material PR transfer from ECC to SRM without Account Assignment
Hello,
When a material PR without account assignment is transferred to SRM. The scenario is determined as direct procurement and system will behave in extended classic scenario.
I would need the PO to be posted in backend ie Classic scenario.
We are in SRM 7.0 using SOA PR transfer from ECC EHP 4 system.
I believe there is consulting note available for this scenario. If any body has the note number please share it.
Thanks,
RohithSymptom
While running Materials Replenishment Planning (MRP) purchase requisitions (PR) will be created in SAP ERP (e.g. after creating a Planned Order in MD10).
Before SAP SRM 7.0 these requisition got the field EPROFILE assigned which enabled the system to extract the PR document to SAP SRM by using report BBP_EXTREQ_TRANSFER. As of SAP SRM 7.0 and SAP ERP 6.04 you configured Business Add-In ME_REQ_SOURCING_CUST to trigger SOA message PurchaseRequestERPSourcingRequest_Out.
After running MRP you notice that no sourcing request SOA message got generated.
Other terms
SOA, MRP, Sourcing, external sourcing,
BBP_EXTREQ_TRANSFER, EPROFILE
MD10, MD14, MD04
Reason and Prerequisites
Program error.
Solution
Due to complexity it is not possible to provide a SAP core correction. However PP-MRP application provides a BAdI interface that gives the possiblity to trigger this functionality of external sourcing.
If you need to use the external sourcing with SAP MRP create a new implementation for BAdI MD_PURREQ_POST and inherite from the class provided in attached correction instruction.
Note 1546980 - MRP PReq: PurchaseRequestERPSouricingRequest_Out not send
1263876 - SAP SRM: Configuration of Procure-to-Pay Scenario
Note 1504247 - ME54/ME55 does not trigger sourcing SOA message
Note 1436550 - Multiple PR scenario PurchaseRequestERPSourcingRequest_Out -
Survey input into a list which already exists?
Can you have a survey populate specific items in a list which already exists?
Example List Columns:
Title
Number
Date
Survey Result A (this is entered by a survey)
Survey Result B (this is entered by the same survey)
Also, can surveys be completed by people who do not have permissions to the site?
Thanks!can surveys be completed by people who do not have permissions to the site?
>> Yes, But user need permission on survey which will be uniquely configured by breaking permission inheritance
>> User need to provide exactly url of survey response so that they can bypass the site
Please 'propose as answer' if it helped you, also 'vote helpful' if you like this reply. -
Hi All,
I have created a keystore file using the keytool utility
The command used by me for that purpose was
D:\Study>keytool -genkey -alias TEST -keypass test123 -storepass test123 -keystore teststore.jks
What is your first and last name?
[Unknown]: TEST
What is the name of your organizational unit?
[Unknown]: TEST
What is the name of your organization?
[Unknown]: TEST
What is the name of your City or Locality?
[Unknown]: TEST
What is the name of your State or Province?
[Unknown]: TEST
What is the two-letter country code for this unit?
[Unknown]: TS
Is <CN=TEST, OU=TEST, O=TEST, L=TEST, ST=TEST, C=TS> correct?
[no]: YES
But when I am trying to load the keystore using my program I am getting an
exception...
Code piece I have used is below.
import java.security.KeyStore;
import java.io.FileInputStream;
import java.security.Key;
public class Crypt{
public static void main(String args[])throws Exception{
KeyStore keyStore = KeyStore.getInstance("JCEKS");
FileInputStream fis = new FileInputStream("teststore.jks");
keyStore.load(fis,"test123".toCharArray());
Key key = keyStore.getKey("TEST","test123".toCharArray());
System.out.println(key);
}The exception I am getting is
Exception in thread "main" java.io.StreamCorruptedException: invalid stream header
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
at com.sun.crypto.provider.JceKeyStore.engineLoad(DashoA6275)
at java.security.KeyStore.load(Unknown Source)
at Crypt.main(Crypt.java:15)
Is this due to some issues while creating the keystore.
I am able to load an already loaded keystore using this program
by just chaning the password details.
ThanksGood question. I have no idea. Maybe sabre150 does?To see what is available on any system I use the follow simple application. Under each provider in the tree there is a a sub-tree that shows the keystores.
Note - please don't look too closely at the code quality. I wrote this some while ago as an aid and have not yet got round to turning it into releasable code!
import java.security.*;
import java.util.Enumeration;
import javax.swing.*;
import javax.swing.tree.*;
import java.awt.*;
import java.util.*;
public class ListAlgorithms extends JFrame
private void getNodes(DefaultMutableTreeNode providerNode, Provider provider, Set<Provider.Service> used, String title, String target)
DefaultMutableTreeNode node = new DefaultMutableTreeNode(title);
for (Provider.Service service : provider.getServices())
if (!used.contains(service) && target.equalsIgnoreCase(service.getType()))
used.add(service);
DefaultMutableTreeNode algNode = new DefaultMutableTreeNode(service.getAlgorithm());
node.add(algNode);
algNode.add(new DefaultMutableTreeNode("class : " + service.getClassName()));
if (node.getChildCount() != 0)
providerNode.add(node);
private ListAlgorithms()
super("JCE Algorithms");
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Providers");
DefaultTreeModel treeModel = new DefaultTreeModel(root);
for (Provider provider : java.security.Security.getProviders())
DefaultMutableTreeNode providerNode = new DefaultMutableTreeNode(provider);
root.add(providerNode);
Set<Provider.Service> used = new HashSet<Provider.Service>();
getNodes(providerNode, provider, used, "Cipher", "cipher");
getNodes(providerNode, provider, used, "Key Agreement", "keyagreement");
getNodes(providerNode, provider, used, "Key Generator", "keygenerator");
getNodes(providerNode, provider, used, "Key Pair Generator", "keypairgenerator");
getNodes(providerNode, provider, used, "Key Factory", "keyfactory");
getNodes(providerNode, provider, used, "Secret Key Factory", "secretkeyfactory");
getNodes(providerNode, provider, used, "Mac", "mac");
getNodes(providerNode, provider, used, "Message Digest", "messagedigest");
getNodes(providerNode, provider, used, "Signature", "signature");
getNodes(providerNode, provider, used, "Algorithm Paramater", "algorithmparameters");
getNodes(providerNode, provider, used, "Algorithm Paramater Generator", "algorithmparametergenerator");
getNodes(providerNode, provider, used, "Key Store", "keystore");
getNodes(providerNode, provider, used, "Secure Random", "securerandom");
getNodes(providerNode, provider, used, "Certificate Factory", "certificatefactory");
getNodes(providerNode, provider, used, "Certificate Store", "certstore");
getNodes(providerNode, provider, used, "Key Manager Factory", "KeyManagerFactory");
getNodes(providerNode, provider, used, "Trust Manager Factory", "TrustManagerFactory");
getNodes(providerNode, provider, used, "SSL Context", "SSLContext");
getNodes(providerNode, provider, used, "Sasl Server Factory", "SaslServerFactory");
getNodes(providerNode, provider, used, "Sasl Client Factory", "SaslClientFactory");
DefaultMutableTreeNode node = new DefaultMutableTreeNode("Other");
for (Provider.Service service : provider.getServices())
if (!used.contains(service))
DefaultMutableTreeNode serviceNode = new DefaultMutableTreeNode(service.getType() + " : " + service.getAlgorithm());
node.add(serviceNode);
serviceNode.add(new DefaultMutableTreeNode("class : " + service.getClassName()));
if (node.getChildCount() != 0)
providerNode.add(node);
JTree tree = new JTree(treeModel);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setEditable(false);
JScrollPane pane = new JScrollPane(tree);
pane.setPreferredSize(new Dimension(200, 200));
getContentPane().add(pane);
pack();
public static void main(String[] args)
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Security.addProvider(new cryptix.jce.provider.CryptixCrypto());
System.out.println("Providers -");
for (Provider provider : java.security.Security.getProviders())
System.out.println(" " + provider.getName());
for (Enumeration en = provider.propertyNames(); en.hasMoreElements();)
String alg = (String)en.nextElement();
if (alg.matches("(?i)cipher.*?pbe.*?aes.*"))
//if (alg.matches("(?i)Cipher.*rc2.*"))
System.out.println(alg);
new ListAlgorithms().setVisible(true);
} -
Initialize/set a base class from a another base class instance
Hi,
How can I initialize/set a base class from a another base class instance? I do not want to do a copy of it.
It would look something like:
class A {...}
class B extends A
B(A a)
// super = a;
setA(A a)
// super = a;
}Thank you.erikku wrote:
Thanks Winton. It is what I did first but A has lots of methods and if methods are later added to A, I will have to edit B again. For those two reasons, I wanted to use inheritance. The part I was not sure with was the way to initialize B's base (A).You pays your money and you takes your choice. One way (this way) you have to provide forwarders; the other way (inheritance) you have to provide constructors (and if A has a lot of em, you may be writing quite a few).
Ask yourself this question: is every B also an A? No exceptions. Ever.
If the answer is 'yes', then inheritance is probably the best way to go.
However, if there is even the remotest chance that an instance of B should not exhibit 100% of the behaviour of A, now or in the future, then the wrapper style is probably what you want.
Another great advantage of the wrapper style is that methods can be added to A without affecting the API for B (unless you want to).
Winston
PS: If your Class A has a constructor or constructors that take a pile of parameters, you might also want to look at the Builder pattern. However, that's not really what we're talking about here, and it should probably be implemented on A anyway. -
Hi all,
In the Effective Java Programming Language Guide by: Joshua Bloch, chapter: 5, item: 21, I came across the following:
+Constants maybe added to a typesafe enum class w/o recompiling its clients b/c the public static object reference fields containing the enumeration constants provide a layer of insulation bet. the client and the enum class.+
What does that mean?
The constants themselves are never compiled into clients as they are in the more common int enum pattern and its String variant.
What does that mean?
Can someone please explain the above in more detail or guide me in another doc./article which helps me get the point?
Any help is greatly appreciated.
Edited by: RonitT on Apr 20, 2009 2:53 PMIn any case, that item should be updated now to advise you to use the Enum types introduced in 1.5 instead of rolling yer own. You are right, I'll use that instead - looks like I have an old edition of book!
Anyway. just for me to understand what you mentioned, since the client code sees the value of RANDOM -- like 17 and not 42 -- so let say my client code has the constants 0 thru 10 and now I need to add new constants from 11 to 20, if I'm confident that my client will never need these new constants, I don't need to give them the new code which contains the values 11 thru 20, is that right? That was you were trying to tell me?
Thanks again. -
Hi,
I have 2 classes from which I want to create a Sub class which inherits from both( don't want to use composition). What is the best way to do this seeing as Java only allows me to extend one class at a time.
ClassA
ClassB
ie
ClassC extends ClassA,ClassBAs you already know, java does not allow multiple inheritance. There is a good reason why. Say classC inherits from classA and classB. If classA has a method called doSomething() and classB has a method called doSomething(), which method will classA use? That's a problem. So, Sun decided to throw out multiple inheritance. Instead, they provide interfaces to simulate multiple inheritance. Since interfaces only allow you to define a method signature, then when a class inherits from an interface, that method must be defined in the actual class. Thus, if interfaceD defines a method called doSomething() and classC inherits from classA (same class used in the previous example) and implements interfaceD and interfaceD defines the method doSomething(), Then classC must declare the doSomething() (well, not actually because it already inherits it from classA, but let's just say for the sake of this argument that we know classes must implement interface methods that they inherit from) method that interfaceD defined. That is, even though classC inherits from classA (which has a method called doSomething()), classC must define the doSomething() method of interfaceD. Now, there isn't a problem. But, you might be asking yourself: But why can't I use the methods of two different classes where these methods have been implemented in both classes. That's the tradeoff.
So, to make a long story short, you have to use interfaces to simulate multiple inheritance. You still get the ability to say that classC "is a" classA and classC "is a" interfaceD and that is very powerful from a polymorphic point of view. But, you lose the ability to do true multiple inheritance.
I hope this helped. -
Error occurred during storage enumeration. The provider`s cache is empty.
Hello all,
I`m currently experimenting with Server 2012 and I faced an issue, while trying to play around with Storage Pools. My Server manager fails on refreshing disk volumes with the above mentioned error. More specifically:
Error occurred during storage enumeration.
Error occurred during enumeration of physical disk and storage pool associations: The provider's cache is empty. [Request = MSFT_SMDiskDriveToPool]
Error occurred during storage enumeration.
Error occurred during enumeration of physical disk: The provider's cache is empty. [Request = MSFT_SMDiskDrive]
There are 6 more errors with the same content, but for different things: Storage pools, Storage Pool capabilities; storage subsystem and pool associations;etc...
Also I see the same error in powershell:
PS C:\Users\Administrator> Get-PhysicalDisk
FriendlyName CanPool OperationalStatus HealthStatus Usage
Size
PhysicalDisk2 False OK Healthy Auto-Select
2 GB
PhysicalDisk3 False OK Healthy Auto-Select
2 GB
PhysicalDisk4 False OK Healthy Auto-Select
1 GB
PhysicalDisk5 False OK Healthy Auto-Select
1 GB
PhysicalDisk0 False OK Healthy Auto-Select
931.51 GB
PhysicalDisk1 False OK Healthy Auto-Select
931.51 GB
Get-PhysicalDisk : The provider's cache is empty. [Request = MSFT_SMDiskDrive]
At line:1 char:1
+ Get-PhysicalDisk
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (MSFT_SMDiskDrive:ROOT/Microsoft/...FT_PhysicalDisk) [Get-PhysicalDisk], C
imException
+ FullyQualifiedErrorId : 40003,Get-PhysicalDisk
I run Update-StorageProviderCache:
PS C:\Windows\system32> Update-StorageProviderCache -DiscoveryLevel Level3 -PassThru
Type Name
Manufacturer
SMP Storage Spaces Management Provider Microsoft
Corporation
with no luck.
What could be the problem. Could somebody also explain me what this cache is used for?
Thanks in advance.
BR,
Svilenin what you pasted you didnt run powershell as admin with "Get-PhysicalDisk" while with "Update-StorageProviderCache
-DiscoveryLevel Level3 -PassThru" you did run it as admin
Run powershell as admin and please see if that makes a difference for you.
MCITP:SA:EA:EMA2010:VA2008R2 -
Security realm - Security:097533 - Developing own authentication provider
hi everyone,
i Developing own authentication provider and i installed a security patch, so while i restarting the weblogic server encountered the below Exeption:
<10/05/2013 05:54:33 PM COT> <Error> <Security> <BEA-090870> <The realm "myrealm" failed to be loaded: weblogic.security.service.SecurityServiceException: com.bea.common.engine.ServiceInitializationException: com.bea.common.engine.SecurityServiceRuntimeException: [Security:097533]SecurityProvider service class name for AS400Realm is not specified..
weblogic.security.service.SecurityServiceException: com.bea.common.engine.ServiceInitializationException: com.bea.common.engine.SecurityServiceRuntimeException: [Security:097533]SecurityProvider service class name for AS400Realm is not specified.
at weblogic.security.service.CSSWLSDelegateImpl.initializeServiceEngine(CSSWLSDelegateImpl.java:341)
at weblogic.security.service.CSSWLSDelegateImpl.initialize(CSSWLSDelegateImpl.java:220)
at weblogic.security.service.CommonSecurityServiceManagerDelegateImpl.InitializeServiceEngine(CommonSecurityServiceManagerDelegateImpl.java:1789)
at weblogic.security.service.CommonSecurityServiceManagerDelegateImpl.initializeRealm(CommonSecurityServiceManagerDelegateImpl.java:443)
at weblogic.security.service.CommonSecurityServiceManagerDelegateImpl.loadRealm(CommonSecurityServiceManagerDelegateImpl.java:841)
Truncated. see log file for complete stacktrace
Caused By: com.bea.common.engine.ServiceInitializationException: com.bea.common.engine.SecurityServiceRuntimeException: [Security:097533]SecurityProvider service class name for AS400Realm is not specified.
at com.bea.common.engine.internal.ServiceEngineImpl.findOrStartService(ServiceEngineImpl.java:365)
at com.bea.common.engine.internal.ServiceEngineImpl.findOrStartService(ServiceEngineImpl.java:315)
at com.bea.common.engine.internal.ServiceEngineImpl.lookupService(ServiceEngineImpl.java:257)
at com.bea.common.engine.internal.ServicesImpl.getService(ServicesImpl.java:72)
at weblogic.security.service.internal.WLSIdentityServiceImpl.initialize(WLSIdentityServiceImpl.java:46)
Truncated. see log file for complete stacktrace
Caused By: com.bea.common.engine.SecurityServiceRuntimeException: [Security:097533]SecurityProvider service class name for AS400Realm is not specified.
at com.bea.common.security.internal.legacy.service.SecurityProviderImpl.init(SecurityProviderImpl.java:42)
at com.bea.common.engine.internal.ServiceEngineImpl.findOrStartService(ServiceEngineImpl.java:363)
at com.bea.common.engine.internal.ServiceEngineImpl.findOrStartService(ServiceEngineImpl.java:315)
at com.bea.common.engine.internal.ServiceEngineImpl.lookupService(ServiceEngineImpl.java:257)
at com.bea.common.engine.internal.ServicesImpl.getService(ServicesImpl.java:72)
Truncated. see log file for complete stacktrace
this is the config.xml :
<domain xmlns="http://xmlns.oracle.com/weblogic/domain" xmlns:sec="http://xmlns.oracle.com/weblogic/security" xmlns:wls="http://xmlns.oracle.com/weblogic/security/wls" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/weblogic/security/xacml http://xmlns.oracle.com/weblogic/security/xacml/1.0/xacml.xsd http://xmlns.oracle.com/weblogic/security/providers/passwordvalidator http://xmlns.oracle.com/weblogic/security/providers/passwordvalidator/1.0/passwordvalidator.xsd http://xmlns.oracle.com/weblogic/domain http://xmlns.oracle.com/weblogic/1.0/domain.xsd http://xmlns.oracle.com/weblogic/security http://xmlns.oracle.com/weblogic/1.0/security.xsd http://xmlns.oracle.com/weblogic/security/wls http://xmlns.oracle.com/weblogic/security/wls/1.0/wls.xsd http://xmlns.oracle.com/weblogic/security/extension http://xmlns.oracle.com/weblogic/1.0/security.xsd">
<name>base_domain</name>
<domain-version>12.1.1.0</domain-version>
<security-configuration>
<name>base_domain</name>
<realm>
<sec:authentication-provider xsi:type="wls:default-authenticatorType"></sec:authentication-provider>
<sec:authentication-provider xsi:type="wls:default-identity-asserterType">
<sec:active-type>AuthenticatedUser</sec:active-type>
</sec:authentication-provider>
<sec:authentication-provider xmlns:ext="http://xmlns.oracle.com/weblogic/security/extension" xsi:type="ext:as400-realmType">
<sec:name>AS400Realm</sec:name>
<sec:control-flag>OPTIONAL</sec:control-flag>
</sec:authentication-provider>
<sec:role-mapper xmlns:xac="http://xmlns.oracle.com/weblogic/security/xacml" xsi:type="xac:xacml-role-mapperType"></sec:role-mapper>
<sec:authorizer xmlns:xac="http://xmlns.oracle.com/weblogic/security/xacml" xsi:type="xac:xacml-authorizerType"></sec:authorizer>
<sec:adjudicator xsi:type="wls:default-adjudicatorType"></sec:adjudicator>
<sec:credential-mapper xsi:type="wls:default-credential-mapperType"></sec:credential-mapper>
<sec:cert-path-provider xsi:type="wls:web-logic-cert-path-providerType"></sec:cert-path-provider>
<sec:cert-path-builder>WebLogicCertPathProvider</sec:cert-path-builder>
<sec:user-lockout-manager>
<sec:lockout-enabled>false</sec:lockout-enabled>
</sec:user-lockout-manager>
<sec:deploy-role-ignored>false</sec:deploy-role-ignored>
<sec:deploy-policy-ignored>false</sec:deploy-policy-ignored>
<sec:security-dd-model>DDOnly</sec:security-dd-model>
<sec:name>myrealm</sec:name>
<sec:password-validator xmlns:pas="http://xmlns.oracle.com/weblogic/security/providers/passwordvalidator" xsi:type="pas:system-password-validatorType">
<sec:name>SystemPasswordValidator</sec:name>
<pas:min-password-length>8</pas:min-password-length>
<pas:min-numeric-or-special-characters>1</pas:min-numeric-or-special-characters>
</sec:password-validator>
</realm>
<default-realm>myrealm</default-realm>
<credential-encrypted>{AES}kyVB/9J9Fbvp11tAnYgn6grV6wQwNZZGHSh2JLQtesxS46Re+QCfIAttNE5JugllQvUHOhE+pz0AnEfYL2p5q2oeRsjqoQz2/1Lg8x+3WMoKic0xnRzw2RWoFjQo3F9x</credential-encrypted>
<node-manager-username>weblogic</node-manager-username>
<node-manager-password-encrypted>{AES}4jkSbv5dMOl6cRpRa4QwB83XVavtq168cV4L+NSFDcI=</node-manager-password-encrypted>
<cross-domain-security-enabled>true</cross-domain-security-enabled>
</security-configuration>
<server>
<name>AdminServer</name>
<listen-address>localhost</listen-address>
<staging-mode>nostage</staging-mode>
</server>
<embedded-ldap>
<name>base_domain</name>
<credential-encrypted>{AES}9YeG1UFRNQzM0v6/j8cFvT9x9fkJUl1FJOWGInl5dax26FgMNEVwKNxOBHvW2opm</credential-encrypted>
</embedded-ldap>
<configuration-version>12.1.1.0</configuration-version>
this is the mbean xml (A400Realmmbean.xml):
<?xml version="1.0" ?>
<!DOCTYPE MBeanType SYSTEM "commo.dtd">
<MBeanType Name = "AS400Realm" DisplayName = "AS400Realm"
Package = "co.com.claro.security"
Extends = "weblogic.management.security.authentication.Authenticator"
PersistPolicy = "OnUpdate"
>
<MbeanAttribute Name = "ProviderClassName" Type = "java.lang.String"
Writeable = "false"
Default =
""co.com.claro.AS400Realm""
/>
<MBeanAttribute Name = "Description" Type = "java.lang.String"
Writeable = "false" Default = ""My Identity Assertion Provider""
/>
<MBeanAttribute Name = "Version" Type = "java.lang.String"
Writeable = "false" Default = ""1.0""
/>
</MBeanType>
and the runtime class:
AS400Realm.java:
* To change this template, choose Tools | Templates
* and open the template in the editor.
package co.com.claro.security;
import java.util.HashMap;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
import weblogic.management.security.ProviderMBean;
import weblogic.security.provider.PrincipalValidatorImpl;
import weblogic.security.spi.AuthenticationProviderV2;
import weblogic.security.spi.IdentityAsserterV2;
import weblogic.security.spi.PrincipalValidator;
import weblogic.security.spi.SecurityServices;
import weblogic.security.principal.WLSGroupImpl;
import weblogic.security.principal.WLSUserImpl;
public final class AS400Realm implements AuthenticationProviderV2
private String description;
// private SimpleSampleAuthenticatorDatabase database;
private LoginModuleControlFlag controlFlag;
// public String PARAM_JAAS_CONTEXT = "jaas-context";
// public String PARAM_DATASOURCE_NAME = "jdbc/Oracle";
// public String DEFAULT_GROUP_NAME = "default";
public void initialize(ProviderMBean mbean, SecurityServices services)
System.out.println("AS400Realm.initialize");
AS400RealmMBean myMBean = (AS400RealmMBean)mbean;
description = myMBean.getDescription() + "\n" + myMBean.getVersion();
// database = new SimpleSampleAuthenticatorDatabase(myMBean);
String flag = myMBean.getControlFlag();
if (flag.equalsIgnoreCase("REQUIRED")) {
controlFlag = LoginModuleControlFlag.REQUIRED;
} else if (flag.equalsIgnoreCase("OPTIONAL")) {
controlFlag = LoginModuleControlFlag.OPTIONAL;
} else if (flag.equalsIgnoreCase("REQUISITE")) {
controlFlag = LoginModuleControlFlag.REQUISITE;
} else if (flag.equalsIgnoreCase("SUFFICIENT")) {
controlFlag = LoginModuleControlFlag.SUFFICIENT;
} else {
throw new IllegalArgumentException("invalid flag value" + flag);
public String getDescription()
return description;
public void shutdown()
System.out.println("AS400Realm.shutdown");
private AppConfigurationEntry getConfiguration(HashMap options)
options.put("PARAM_DATASOURCE_NAME", "jdbc/Oracle");
return new
AppConfigurationEntry(
"co.com.claro.security.AS400LoginModule",
controlFlag,
options
public AppConfigurationEntry getLoginModuleConfiguration()
HashMap options = new HashMap();
return getConfiguration(options);
public AppConfigurationEntry getAssertionModuleConfiguration()
HashMap options = new HashMap();
options.put("IdentityAssertion","true");
return getConfiguration(options);
public PrincipalValidator getPrincipalValidator()
return new PrincipalValidatorImpl();
public IdentityAsserterV2 getIdentityAsserter()
return null;
AS400LoginModule.java :
* To change this template, choose Tools | Templates
* and open the template in the editor.
package co.com.claro.security;
import com.ibm.as400.access.AS400;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.spi.LoginModule;
import javax.sql.DataSource;
import weblogic.security.spi.WLSGroup;
import weblogic.security.spi.WLSUser;
import weblogic.security.principal.WLSGroupImpl;
import weblogic.security.principal.WLSUserImpl;
* @author dmunoz
final public class AS400LoginModule implements LoginModule {
private Subject subject;
private CallbackHandler callbackHandler;
private String PARAM_DATASOURCE_NAME = "jdbc/Oracle";
private String DEFAULT_GROUP_NAME = "default";
// Determine whether this is a login or assert identity
private boolean isIdentityAssertion;
// Authentication status
private boolean loginSucceeded;
private boolean principalsInSubject;
private Vector principalsForSubject = new Vector();
public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
// only called (once!) after the constructor and before login
System.out.println("SimpleSampleLoginModuleImpl.initialize");
this.subject = subject;
this.callbackHandler = callbackHandler;
// Check for Identity Assertion option
isIdentityAssertion =
"true".equalsIgnoreCase((String) options.get("IdentityAssertion"));
private boolean authenticateAS400(String user, String passwd) throws Exception {
String host ="172.31.2.80";//Config.getProperty(Config.AS400_AUTHENTICATION_HOST);
AS400 as400System;
as400System = new AS400(host, user, passwd);
return as400System.validateSignon();
public boolean login() throws LoginException {
// only called (once!) after initialize
System.out.println("SimpleSampleLoginModuleImpl.login");
// loginSucceeded should be false
// principalsInSubject should be false
Callback[] callbacks = getCallbacks();
String userName = getUserName(callbacks);
if (userName.length() > 0) {
if (!isIdentityAssertion) {
String passwordHave = getPasswordHave(userName, callbacks);
try{
loginSucceeded = authenticateAS400(userName, passwordHave);
}catch(Exception e){
Logger.getLogger(AS400LoginModule.class.getName()).log(Level.WARNING, null, e);
throw new LoginException(e.getMessage());
} else {
// anonymous login - let it through?
System.out.println("\tempty userName");
if (loginSucceeded) {
principalsForSubject.add(new WLSUserImpl(userName));
addGroupsForSubject(userName);
return loginSucceeded;
public boolean commit() throws LoginException {
// only called (once!) after login
// loginSucceeded should be true or false
// principalsInSubject should be false
// user should be null if !loginSucceeded, null or not-null otherwise
// group should be null if user == null, null or not-null otherwise
System.out.println("SimpleSampleLoginModule.commit");
if (loginSucceeded) {
subject.getPrincipals().addAll(principalsForSubject);
principalsInSubject = true;
return true;
} else {
return false;
public boolean abort() throws LoginException {
// The abort method is called to abort the authentication process. This is
// phase 2 of authentication when phase 1 fails. It is called if the
// LoginContext's overall authentication failed.
// loginSucceeded should be true or false
// user should be null if !loginSucceeded, otherwise null or not-null
// group should be null if user == null, otherwise null or not-null
// principalsInSubject should be false if user is null, otherwise true
// or false
System.out.println("SimpleSampleLoginModule.abort");
if (principalsInSubject) {
subject.getPrincipals().removeAll(principalsForSubject);
principalsInSubject = false;
return true;
public boolean logout() throws LoginException {
// should never be called
System.out.println("SimpleSampleLoginModule.logout");
return true;
private void throwLoginException(String msg) throws LoginException {
System.out.println("Throwing LoginException(" + msg + ")");
throw new LoginException(msg);
private void throwFailedLoginException(String msg) throws FailedLoginException {
System.out.println("Throwing FailedLoginException(" + msg + ")");
throw new FailedLoginException(msg);
private Callback[] getCallbacks() throws LoginException {
if (callbackHandler == null) {
throwLoginException("No CallbackHandler Specified");
Callback[] callbacks;
if (isIdentityAssertion) {
callbacks = new Callback[1];
} else {
callbacks = new Callback[2];
callbacks[1] = new PasswordCallback("password: ", false);
callbacks[0] = new NameCallback("username: ");
try {
callbackHandler.handle(callbacks);
} catch (IOException e) {
throw new LoginException(e.toString());
} catch (UnsupportedCallbackException e) {
throwLoginException(e.toString() + " " + e.getCallback().toString());
return callbacks;
private String getUserName(Callback[] callbacks) throws LoginException {
String userName = ((NameCallback) callbacks[0]).getName();
if (userName == null) {
throwLoginException("Username not supplied.");
System.out.println("\tuserName\t= " + userName);
return userName;
private void addGroupsForSubject(String userName) {
try {
for (Enumeration e = getGroupNamesAS400(userName);
e.hasMoreElements();) {
String groupName = (String) e.nextElement();
System.out.println("\tgroupName\t= " + groupName);
principalsForSubject.add(new WLSGroupImpl(groupName));
} catch (Exception ex) {
Logger.getLogger(AS400LoginModule.class.getName()).log(Level.SEVERE, null, ex);
public Enumeration getGroupNamesAS400(String usuario)
throws Exception {
if(usuario == null) {
throw new Exception("Usuario no puede ser vacio");
Vector<String> grupos = new Vector<String>();
grupos.add(DEFAULT_GROUP_NAME);
Connection conn = null;
ResultSet rs = null;
PreparedStatement statement = null;
try {
Context c = new InitialContext();
DataSource dst = (DataSource) c.lookup(PARAM_DATASOURCE_NAME);
conn = dst.getConnection();
String query = "SELECT COD_ROL AS ROL " +
"FROM gestionnew.us_rol_perfil " +
"JOIN gestionnew.usuarios " +
"ON us_rol_perfil.id_perfil = usuarios.id_perfil " +
"WHERE upper(usuarios.usuariorr) = ?";
statement = conn.prepareStatement(query);
statement.setString(1, usuario.toUpperCase());
rs = statement.executeQuery();
while (rs.next()) {
grupos.add(rs.getString("ROL"));
} catch (SQLException ex) {
Logger.getLogger(AS400LoginModule.class.getName()).log(Level.SEVERE, null, ex);
} catch (NamingException ex) {
Logger.getLogger(AS400LoginModule.class.getName()).log(Level.SEVERE, null, ex);
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException ex) {
Logger.getLogger(AS400LoginModule.class.getName()).log(Level.SEVERE, null, ex);
if (rs != null) {
try {
rs.close();
} catch (SQLException ex) {
Logger.getLogger(AS400LoginModule.class.getName()).log(Level.SEVERE, null, ex);
if (statement != null) {
try {
statement.close();
} catch (SQLException ex) {
Logger.getLogger(AS400LoginModule.class.getName()).log(Level.SEVERE, null, ex);
return grupos.elements();
private String getPasswordHave(String userName, Callback[] callbacks) throws
LoginException {
PasswordCallback passwordCallback = (PasswordCallback) callbacks[1];
char[] password = passwordCallback.getPassword();
passwordCallback.clearPassword();
if (password == null || password.length < 1) {
throwLoginException("Authentication Failed: User " + userName +
". Password not supplied");
String passwd = new String(password);
System.out.println("\tpasswordHave\t= " + passwd);
return passwd;
thankshi everyone,
i Developing own authentication provider and i installed a security patch, so while i restarting the weblogic server encountered the below Exeption:
<10/05/2013 05:54:33 PM COT> <Error> <Security> <BEA-090870> <The realm "myrealm" failed to be loaded: weblogic.security.service.SecurityServiceException: com.bea.common.engine.ServiceInitializationException: com.bea.common.engine.SecurityServiceRuntimeException: [Security:097533]SecurityProvider service class name for AS400Realm is not specified..
weblogic.security.service.SecurityServiceException: com.bea.common.engine.ServiceInitializationException: com.bea.common.engine.SecurityServiceRuntimeException: [Security:097533]SecurityProvider service class name for AS400Realm is not specified.
at weblogic.security.service.CSSWLSDelegateImpl.initializeServiceEngine(CSSWLSDelegateImpl.java:341)
at weblogic.security.service.CSSWLSDelegateImpl.initialize(CSSWLSDelegateImpl.java:220)
at weblogic.security.service.CommonSecurityServiceManagerDelegateImpl.InitializeServiceEngine(CommonSecurityServiceManagerDelegateImpl.java:1789)
at weblogic.security.service.CommonSecurityServiceManagerDelegateImpl.initializeRealm(CommonSecurityServiceManagerDelegateImpl.java:443)
at weblogic.security.service.CommonSecurityServiceManagerDelegateImpl.loadRealm(CommonSecurityServiceManagerDelegateImpl.java:841)
Truncated. see log file for complete stacktrace
Caused By: com.bea.common.engine.ServiceInitializationException: com.bea.common.engine.SecurityServiceRuntimeException: [Security:097533]SecurityProvider service class name for AS400Realm is not specified.
at com.bea.common.engine.internal.ServiceEngineImpl.findOrStartService(ServiceEngineImpl.java:365)
at com.bea.common.engine.internal.ServiceEngineImpl.findOrStartService(ServiceEngineImpl.java:315)
at com.bea.common.engine.internal.ServiceEngineImpl.lookupService(ServiceEngineImpl.java:257)
at com.bea.common.engine.internal.ServicesImpl.getService(ServicesImpl.java:72)
at weblogic.security.service.internal.WLSIdentityServiceImpl.initialize(WLSIdentityServiceImpl.java:46)
Truncated. see log file for complete stacktrace
Caused By: com.bea.common.engine.SecurityServiceRuntimeException: [Security:097533]SecurityProvider service class name for AS400Realm is not specified.
at com.bea.common.security.internal.legacy.service.SecurityProviderImpl.init(SecurityProviderImpl.java:42)
at com.bea.common.engine.internal.ServiceEngineImpl.findOrStartService(ServiceEngineImpl.java:363)
at com.bea.common.engine.internal.ServiceEngineImpl.findOrStartService(ServiceEngineImpl.java:315)
at com.bea.common.engine.internal.ServiceEngineImpl.lookupService(ServiceEngineImpl.java:257)
at com.bea.common.engine.internal.ServicesImpl.getService(ServicesImpl.java:72)
Truncated. see log file for complete stacktrace
this is the config.xml :
<domain xmlns="http://xmlns.oracle.com/weblogic/domain" xmlns:sec="http://xmlns.oracle.com/weblogic/security" xmlns:wls="http://xmlns.oracle.com/weblogic/security/wls" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/weblogic/security/xacml http://xmlns.oracle.com/weblogic/security/xacml/1.0/xacml.xsd http://xmlns.oracle.com/weblogic/security/providers/passwordvalidator http://xmlns.oracle.com/weblogic/security/providers/passwordvalidator/1.0/passwordvalidator.xsd http://xmlns.oracle.com/weblogic/domain http://xmlns.oracle.com/weblogic/1.0/domain.xsd http://xmlns.oracle.com/weblogic/security http://xmlns.oracle.com/weblogic/1.0/security.xsd http://xmlns.oracle.com/weblogic/security/wls http://xmlns.oracle.com/weblogic/security/wls/1.0/wls.xsd http://xmlns.oracle.com/weblogic/security/extension http://xmlns.oracle.com/weblogic/1.0/security.xsd">
<name>base_domain</name>
<domain-version>12.1.1.0</domain-version>
<security-configuration>
<name>base_domain</name>
<realm>
<sec:authentication-provider xsi:type="wls:default-authenticatorType"></sec:authentication-provider>
<sec:authentication-provider xsi:type="wls:default-identity-asserterType">
<sec:active-type>AuthenticatedUser</sec:active-type>
</sec:authentication-provider>
<sec:authentication-provider xmlns:ext="http://xmlns.oracle.com/weblogic/security/extension" xsi:type="ext:as400-realmType">
<sec:name>AS400Realm</sec:name>
<sec:control-flag>OPTIONAL</sec:control-flag>
</sec:authentication-provider>
<sec:role-mapper xmlns:xac="http://xmlns.oracle.com/weblogic/security/xacml" xsi:type="xac:xacml-role-mapperType"></sec:role-mapper>
<sec:authorizer xmlns:xac="http://xmlns.oracle.com/weblogic/security/xacml" xsi:type="xac:xacml-authorizerType"></sec:authorizer>
<sec:adjudicator xsi:type="wls:default-adjudicatorType"></sec:adjudicator>
<sec:credential-mapper xsi:type="wls:default-credential-mapperType"></sec:credential-mapper>
<sec:cert-path-provider xsi:type="wls:web-logic-cert-path-providerType"></sec:cert-path-provider>
<sec:cert-path-builder>WebLogicCertPathProvider</sec:cert-path-builder>
<sec:user-lockout-manager>
<sec:lockout-enabled>false</sec:lockout-enabled>
</sec:user-lockout-manager>
<sec:deploy-role-ignored>false</sec:deploy-role-ignored>
<sec:deploy-policy-ignored>false</sec:deploy-policy-ignored>
<sec:security-dd-model>DDOnly</sec:security-dd-model>
<sec:name>myrealm</sec:name>
<sec:password-validator xmlns:pas="http://xmlns.oracle.com/weblogic/security/providers/passwordvalidator" xsi:type="pas:system-password-validatorType">
<sec:name>SystemPasswordValidator</sec:name>
<pas:min-password-length>8</pas:min-password-length>
<pas:min-numeric-or-special-characters>1</pas:min-numeric-or-special-characters>
</sec:password-validator>
</realm>
<default-realm>myrealm</default-realm>
<credential-encrypted>{AES}kyVB/9J9Fbvp11tAnYgn6grV6wQwNZZGHSh2JLQtesxS46Re+QCfIAttNE5JugllQvUHOhE+pz0AnEfYL2p5q2oeRsjqoQz2/1Lg8x+3WMoKic0xnRzw2RWoFjQo3F9x</credential-encrypted>
<node-manager-username>weblogic</node-manager-username>
<node-manager-password-encrypted>{AES}4jkSbv5dMOl6cRpRa4QwB83XVavtq168cV4L+NSFDcI=</node-manager-password-encrypted>
<cross-domain-security-enabled>true</cross-domain-security-enabled>
</security-configuration>
<server>
<name>AdminServer</name>
<listen-address>localhost</listen-address>
<staging-mode>nostage</staging-mode>
</server>
<embedded-ldap>
<name>base_domain</name>
<credential-encrypted>{AES}9YeG1UFRNQzM0v6/j8cFvT9x9fkJUl1FJOWGInl5dax26FgMNEVwKNxOBHvW2opm</credential-encrypted>
</embedded-ldap>
<configuration-version>12.1.1.0</configuration-version>
this is the mbean xml (A400Realmmbean.xml):
<?xml version="1.0" ?>
<!DOCTYPE MBeanType SYSTEM "commo.dtd">
<MBeanType Name = "AS400Realm" DisplayName = "AS400Realm"
Package = "co.com.claro.security"
Extends = "weblogic.management.security.authentication.Authenticator"
PersistPolicy = "OnUpdate"
>
<MbeanAttribute Name = "ProviderClassName" Type = "java.lang.String"
Writeable = "false"
Default =
""co.com.claro.AS400Realm""
/>
<MBeanAttribute Name = "Description" Type = "java.lang.String"
Writeable = "false" Default = ""My Identity Assertion Provider""
/>
<MBeanAttribute Name = "Version" Type = "java.lang.String"
Writeable = "false" Default = ""1.0""
/>
</MBeanType>
and the runtime class:
AS400Realm.java:
* To change this template, choose Tools | Templates
* and open the template in the editor.
package co.com.claro.security;
import java.util.HashMap;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
import weblogic.management.security.ProviderMBean;
import weblogic.security.provider.PrincipalValidatorImpl;
import weblogic.security.spi.AuthenticationProviderV2;
import weblogic.security.spi.IdentityAsserterV2;
import weblogic.security.spi.PrincipalValidator;
import weblogic.security.spi.SecurityServices;
import weblogic.security.principal.WLSGroupImpl;
import weblogic.security.principal.WLSUserImpl;
public final class AS400Realm implements AuthenticationProviderV2
private String description;
// private SimpleSampleAuthenticatorDatabase database;
private LoginModuleControlFlag controlFlag;
// public String PARAM_JAAS_CONTEXT = "jaas-context";
// public String PARAM_DATASOURCE_NAME = "jdbc/Oracle";
// public String DEFAULT_GROUP_NAME = "default";
public void initialize(ProviderMBean mbean, SecurityServices services)
System.out.println("AS400Realm.initialize");
AS400RealmMBean myMBean = (AS400RealmMBean)mbean;
description = myMBean.getDescription() + "\n" + myMBean.getVersion();
// database = new SimpleSampleAuthenticatorDatabase(myMBean);
String flag = myMBean.getControlFlag();
if (flag.equalsIgnoreCase("REQUIRED")) {
controlFlag = LoginModuleControlFlag.REQUIRED;
} else if (flag.equalsIgnoreCase("OPTIONAL")) {
controlFlag = LoginModuleControlFlag.OPTIONAL;
} else if (flag.equalsIgnoreCase("REQUISITE")) {
controlFlag = LoginModuleControlFlag.REQUISITE;
} else if (flag.equalsIgnoreCase("SUFFICIENT")) {
controlFlag = LoginModuleControlFlag.SUFFICIENT;
} else {
throw new IllegalArgumentException("invalid flag value" + flag);
public String getDescription()
return description;
public void shutdown()
System.out.println("AS400Realm.shutdown");
private AppConfigurationEntry getConfiguration(HashMap options)
options.put("PARAM_DATASOURCE_NAME", "jdbc/Oracle");
return new
AppConfigurationEntry(
"co.com.claro.security.AS400LoginModule",
controlFlag,
options
public AppConfigurationEntry getLoginModuleConfiguration()
HashMap options = new HashMap();
return getConfiguration(options);
public AppConfigurationEntry getAssertionModuleConfiguration()
HashMap options = new HashMap();
options.put("IdentityAssertion","true");
return getConfiguration(options);
public PrincipalValidator getPrincipalValidator()
return new PrincipalValidatorImpl();
public IdentityAsserterV2 getIdentityAsserter()
return null;
AS400LoginModule.java :
* To change this template, choose Tools | Templates
* and open the template in the editor.
package co.com.claro.security;
import com.ibm.as400.access.AS400;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.spi.LoginModule;
import javax.sql.DataSource;
import weblogic.security.spi.WLSGroup;
import weblogic.security.spi.WLSUser;
import weblogic.security.principal.WLSGroupImpl;
import weblogic.security.principal.WLSUserImpl;
* @author dmunoz
final public class AS400LoginModule implements LoginModule {
private Subject subject;
private CallbackHandler callbackHandler;
private String PARAM_DATASOURCE_NAME = "jdbc/Oracle";
private String DEFAULT_GROUP_NAME = "default";
// Determine whether this is a login or assert identity
private boolean isIdentityAssertion;
// Authentication status
private boolean loginSucceeded;
private boolean principalsInSubject;
private Vector principalsForSubject = new Vector();
public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
// only called (once!) after the constructor and before login
System.out.println("SimpleSampleLoginModuleImpl.initialize");
this.subject = subject;
this.callbackHandler = callbackHandler;
// Check for Identity Assertion option
isIdentityAssertion =
"true".equalsIgnoreCase((String) options.get("IdentityAssertion"));
private boolean authenticateAS400(String user, String passwd) throws Exception {
String host ="172.31.2.80";//Config.getProperty(Config.AS400_AUTHENTICATION_HOST);
AS400 as400System;
as400System = new AS400(host, user, passwd);
return as400System.validateSignon();
public boolean login() throws LoginException {
// only called (once!) after initialize
System.out.println("SimpleSampleLoginModuleImpl.login");
// loginSucceeded should be false
// principalsInSubject should be false
Callback[] callbacks = getCallbacks();
String userName = getUserName(callbacks);
if (userName.length() > 0) {
if (!isIdentityAssertion) {
String passwordHave = getPasswordHave(userName, callbacks);
try{
loginSucceeded = authenticateAS400(userName, passwordHave);
}catch(Exception e){
Logger.getLogger(AS400LoginModule.class.getName()).log(Level.WARNING, null, e);
throw new LoginException(e.getMessage());
} else {
// anonymous login - let it through?
System.out.println("\tempty userName");
if (loginSucceeded) {
principalsForSubject.add(new WLSUserImpl(userName));
addGroupsForSubject(userName);
return loginSucceeded;
public boolean commit() throws LoginException {
// only called (once!) after login
// loginSucceeded should be true or false
// principalsInSubject should be false
// user should be null if !loginSucceeded, null or not-null otherwise
// group should be null if user == null, null or not-null otherwise
System.out.println("SimpleSampleLoginModule.commit");
if (loginSucceeded) {
subject.getPrincipals().addAll(principalsForSubject);
principalsInSubject = true;
return true;
} else {
return false;
public boolean abort() throws LoginException {
// The abort method is called to abort the authentication process. This is
// phase 2 of authentication when phase 1 fails. It is called if the
// LoginContext's overall authentication failed.
// loginSucceeded should be true or false
// user should be null if !loginSucceeded, otherwise null or not-null
// group should be null if user == null, otherwise null or not-null
// principalsInSubject should be false if user is null, otherwise true
// or false
System.out.println("SimpleSampleLoginModule.abort");
if (principalsInSubject) {
subject.getPrincipals().removeAll(principalsForSubject);
principalsInSubject = false;
return true;
public boolean logout() throws LoginException {
// should never be called
System.out.println("SimpleSampleLoginModule.logout");
return true;
private void throwLoginException(String msg) throws LoginException {
System.out.println("Throwing LoginException(" + msg + ")");
throw new LoginException(msg);
private void throwFailedLoginException(String msg) throws FailedLoginException {
System.out.println("Throwing FailedLoginException(" + msg + ")");
throw new FailedLoginException(msg);
private Callback[] getCallbacks() throws LoginException {
if (callbackHandler == null) {
throwLoginException("No CallbackHandler Specified");
Callback[] callbacks;
if (isIdentityAssertion) {
callbacks = new Callback[1];
} else {
callbacks = new Callback[2];
callbacks[1] = new PasswordCallback("password: ", false);
callbacks[0] = new NameCallback("username: ");
try {
callbackHandler.handle(callbacks);
} catch (IOException e) {
throw new LoginException(e.toString());
} catch (UnsupportedCallbackException e) {
throwLoginException(e.toString() + " " + e.getCallback().toString());
return callbacks;
private String getUserName(Callback[] callbacks) throws LoginException {
String userName = ((NameCallback) callbacks[0]).getName();
if (userName == null) {
throwLoginException("Username not supplied.");
System.out.println("\tuserName\t= " + userName);
return userName;
private void addGroupsForSubject(String userName) {
try {
for (Enumeration e = getGroupNamesAS400(userName);
e.hasMoreElements();) {
String groupName = (String) e.nextElement();
System.out.println("\tgroupName\t= " + groupName);
principalsForSubject.add(new WLSGroupImpl(groupName));
} catch (Exception ex) {
Logger.getLogger(AS400LoginModule.class.getName()).log(Level.SEVERE, null, ex);
public Enumeration getGroupNamesAS400(String usuario)
throws Exception {
if(usuario == null) {
throw new Exception("Usuario no puede ser vacio");
Vector<String> grupos = new Vector<String>();
grupos.add(DEFAULT_GROUP_NAME);
Connection conn = null;
ResultSet rs = null;
PreparedStatement statement = null;
try {
Context c = new InitialContext();
DataSource dst = (DataSource) c.lookup(PARAM_DATASOURCE_NAME);
conn = dst.getConnection();
String query = "SELECT COD_ROL AS ROL " +
"FROM gestionnew.us_rol_perfil " +
"JOIN gestionnew.usuarios " +
"ON us_rol_perfil.id_perfil = usuarios.id_perfil " +
"WHERE upper(usuarios.usuariorr) = ?";
statement = conn.prepareStatement(query);
statement.setString(1, usuario.toUpperCase());
rs = statement.executeQuery();
while (rs.next()) {
grupos.add(rs.getString("ROL"));
} catch (SQLException ex) {
Logger.getLogger(AS400LoginModule.class.getName()).log(Level.SEVERE, null, ex);
} catch (NamingException ex) {
Logger.getLogger(AS400LoginModule.class.getName()).log(Level.SEVERE, null, ex);
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException ex) {
Logger.getLogger(AS400LoginModule.class.getName()).log(Level.SEVERE, null, ex);
if (rs != null) {
try {
rs.close();
} catch (SQLException ex) {
Logger.getLogger(AS400LoginModule.class.getName()).log(Level.SEVERE, null, ex);
if (statement != null) {
try {
statement.close();
} catch (SQLException ex) {
Logger.getLogger(AS400LoginModule.class.getName()).log(Level.SEVERE, null, ex);
return grupos.elements();
private String getPasswordHave(String userName, Callback[] callbacks) throws
LoginException {
PasswordCallback passwordCallback = (PasswordCallback) callbacks[1];
char[] password = passwordCallback.getPassword();
passwordCallback.clearPassword();
if (password == null || password.length < 1) {
throwLoginException("Authentication Failed: User " + userName +
". Password not supplied");
String passwd = new String(password);
System.out.println("\tpasswordHave\t= " + passwd);
return passwd;
thanks
Maybe you are looking for
-
I want my iCloud to be private , I have a large family w different devices and different apple Ids , can they be accessed or linked in any way?
-
My devices (Mac Pro, iPad
Until today my Mac Pro, iPad and iPhone (3Gs) have been sync'ing with iCloud. Today my iCloud calendar, phonebook and email are all empty. The information on my devices is intact. New information still sync's between my devices but does not show u
-
FV50 should only allow to park and Fbv0 should allow to post
Dear Gurus We have a requirement where we want users to park document via transaction via fv50 and post via fbv0, as transaction fv50 does allow users to post , I have tried to create transaction variant shd0 and hidden posting option but user still
-
IDoc Listener connecting to a clustered SAP
We have SAP MII V12.1 loaded to Netweaver CE 7.11 EHP1, and want to connect one of the Resource Adapters (an iDoc Listener in this case) to a clustered SAP environment by connecting to a message server / system ID / logon group combination. I can suc
-
All in one printer j6480 unable to configure wirelessly
i had the wireless feture installed but now it doesn't work tried to reconfigure but no resolution. I downloaded the drivers from hp but when it opens the graphics are there but no text. really frustrated. been going around in circles.